Reasons for the media sources chosen: News 24 : Recognized by APP Annie (App Annie is the standard in app analytics and app market data) as the most known South African internet media source. (Chinese Academy of Cyberspace Studiespublisher=Springer (15 September 2018). World Internet Development Report 2017: Translated by Peng Ping. p. 203. ISBN 9783662575246. OCLC 1052766508.)

Times Live : Claim to be South Africa’s second-biggest news website, published by Arena Holdings (Times Live website). No evidence found to disprove this claim. In top 10 of most visited publication websites for South Africa.

EWN : Not much info but it can be considered to be popular because it originated from 2 radio stations (KFM and CapeTalk), Makes it a popular and people hear about it without actively having to go and search for the news agency themselves. In top 10 of most visited publication websites for South Africa.

eNCA: Not much info but seems popular. Used to E News from TV channel. Might not be as trustworthy as there has been complaints about racism recently. In top 10 of most visited publication websites for South Africa.

SABC: National news company with government ties. Reaches a wide variety of viewers in different languages. The company is both state owned and a public broadcaster company.https://www.businesslive.co.za/bd/national/media/2015-05-20-sabc-both-state-owned-company-and-public-broadcaster-minister-says/

Chapter 10 of the Constitution of the Republic of South Africa, 1996 makes provision for good governance of news media and what they publish.

The other 4 of the 5 is ranked among the top 10 most visited publication sites websites in south africa as found by https://mybroadband.co.za/news/internet/358453-here-are-south-africas-most-popular-news-websites.html. These sites are the first sites on the top 10 list of publication sites that include general news along with news about covid-19 that do not have major historical issues that could bring their credibility in question. Reasons that other news or publishing sources that are ranked higher were not used is due to the fact that these sources either only focus on specific news like new technology or financial aspects, or these sources are not as popular throughout the whole of South Africa.

Importing Libraries

library(tidytext)
library(tidyverse)
library(textdata)
library(sentimentr)
library(stringr)
library(stringi)
library(rtweet)
library(ggplot2)
library(tidyr)
library(dplyr)
library(scales)
library(readr)
library(lubridate)
library(topicmodels)
library(quanteda)
library(reshape2)
library(zoo)

Importing data of collected tweets. This was done to see which lexicon works best between VADER and SentimentR

media_agency_df <- read_csv("data_in/media_agency_tweets.csv")
media_agency_df <- media_agency_df[ , colSums(is.na(media_agency_df)) < nrow(media_agency_df)]
media_agency_df <- media_agency_df %>% mutate("X1" = row_number())

Wrangeling and cleaning data

#Cleaning data
media_agency_df <- media_agency_df %>%
  mutate(text = gsub(" ?(f|ht)tp(s?)://(.*)[.][a-z]+", "", text),
         text = gsub("&amp", "", text),
         text = gsub("(RT|via)((?:\\b\\W*@\\w+)+)", "", text),
         text = gsub("@\\w+", "", text),
         text = gsub("[[:punct:]]", "", text),
         text = gsub("[[:digit:]]", "", text),
         text = gsub("http\\w+", "", text),
         text = gsub("[ \t]{2,}", "", text),
         text = gsub("^\\s+|\\s+$", "", text),
         text = gsub("&amp", "", text)) %>%
  mutate(text = str_replace_all(text," "," "),
         text = str_replace_all(text,"RT @[a-z,A-Z]*: "," "),
         text = str_replace_all(text,"#[a-z,A-Z]*"," "),
         text = str_replace_all(text,"@[a-z,A-Z]*"," "))


#tidying data
tidy_covid_media_df <- media_agency_df %>%
  #filter(str_detect(text, fixed(covid_dictionary, ignore_case = TRUE))) %>%
  filter(!str_detect(text, "^RT")) %>%
  mutate(text = gsub(" ?(f|ht)tp(s?)://(.*)[.][a-z]+", "", text)) %>%
  unnest_tokens(word, text, token = "tweets") %>%
  filter(!word %in% stop_words$word,
         !word %in% str_remove_all(stop_words$word, "'"),
         str_detect(word, "[a-z]"),
         !(word =="#sabcnews" |
             word =="#enca" |
             word =="https" |
             word =="#dstv403" |
             word =="t.co" |
             word =="rt" |
             word =="amp"))
#finding the screen names of media angencies
agencies<- media_agency_df %>%
  select(screen_name) 
agencies %>%
  distinct(screen_name)

Seniment Analysis with SentimentR


mytext<- media_agency_df 

mytext <- get_sentences(mytext$text)
sr_data <-sentiment(mytext)
#write_csv(sr_data,"data_in/sentimentr_data.csv")

Adding time data to sentiment df

time_data <- media_agency_df %>%
  select(X1,created_at,screen_name)

SentiR_data <-left_join(time_data,sr_data,
                        by=c("X1"="element_id"))
#write_csv(SentiR_data,"data_in/sr_df_time.csv")

Modeling the time data

#setting the date format
#NB only run date format once
SentiR_data$created_at = ymd_hms(SentiR_data$created_at)
#filtering by news agency
news24<- SentiR_data %>%
  filter(screen_name=="News24")

times_live<-SentiR_data %>%
  filter(screen_name=="TimesLIVE")

dailymaverick<-SentiR_data %>%
  filter(screen_name=="dailymaverick")

sabc<-SentiR_data %>%
  filter(screen_name=="SABCNews")

eNCA<-SentiR_data %>%
  filter(screen_name=="eNCA")

Graphs plotting the sentiment of the different news agencies over time. As one can see, they all tend to maintain a neutral stance with some fluctuations at time.

#graph for News24 sentiment over time
ggplot(data=news24, aes(x=created_at, y=rollmean(sentiment, 30,  na.pad=TRUE))) +
       geom_line(color="pink", size=.5)+
  geom_smooth() +
  theme_minimal()+
  facet_wrap(~screen_name) +
  scale_y_continuous(expand = c(0,0), breaks = c(-0.4,-0.2,0,0.2,0.4)) +
  ylim(c(-0.4, 0.4))
#graph for Times Live sentiment over time
ggplot(data=times_live, aes(x=created_at, y=rollmean(sentiment, 30,  na.pad=TRUE))) +
       geom_line(color="pink", size=.5)+
  geom_smooth() +
  theme_minimal()+
  facet_wrap(~screen_name) +
  scale_y_continuous(expand = c(0,0), breaks = c(-0.4,-0.2,0,0.2,0.4)) +
  ylim(c(-0.4, 0.4))
#graph for EWN sentiment over time
ggplot(data=dailymaverick, aes(x=created_at, y=rollmean(sentiment, 30,  na.pad=TRUE))) +
       geom_line(color="pink", size=.5)+
  geom_smooth() +
  theme_minimal()+
  facet_wrap(~screen_name) +
  scale_y_continuous(expand = c(0,0), breaks = c(-0.4,-0.2,0,0.2,0.4)) +
  ylim(c(-0.4, 0.4))
#graph for eNCA sentiment over time
ggplot(data=eNCA, aes(x=created_at, y=rollmean(sentiment, 30,  na.pad=TRUE))) +
       geom_line(color="pink", size=.5)+
  geom_smooth() +
  theme_minimal()+
  facet_wrap(~screen_name) +
  scale_y_continuous(expand = c(0,0), breaks = c(-0.4,-0.2,0,0.2,0.4)) +
  ylim(c(-0.4, 0.4))
#graph for SABC sentiment over time
ggplot(data=sabc, aes(x=created_at, y=rollmean(sentiment, 30,  na.pad=TRUE))) +
       geom_line(color="pink", size=.5)+
  geom_smooth() +
  theme_minimal()+
  facet_wrap(~screen_name) +
  scale_y_continuous(expand = c(0,0), breaks = c(-0.4,-0.2,0,0.2,0.4)) +
  ylim(c(-0.4, 0.4))

Topic Modelling


tidy_matrix <- tidy_covid_media_df %>% count(screen_name, word) %>% cast_dfm(screen_name, word, n)

 
media_lda <- LDA(tidy_matrix, k = 4, control = list(seed = 1234))
media_lda
media_topics <- tidy(media_lda, matrix = "beta")
media_topics
media_top_terms <- media_topics %>%
group_by(topic) %>%
slice_max(beta, n = 10) %>%
ungroup() %>%
arrange(topic, -beta)
 

media_top_terms %>%
mutate(term = reorder_within(term, beta, topic)) %>%
ggplot(aes(beta, term, fill = factor(topic))) +
geom_col(show.legend = FALSE) +
facet_wrap(~ topic, scales = "free") +
scale_y_reordered()

Vader stuff. Here we created a dictionary with covid related terms that are commonly used to help us search through the dataframes for relevent tweets and posts.

vader_data<- read_csv("data_in/vader_df.csv")

covid_dictionary <- c("herd", "immunity", "incubation", "job", "loss", "Kits", "lockdown", "mask", "N95", "outbreak", "pandemic", "quarantine", "recovery", "sanitiser", "transmission", "Underlying", "conditions", "Ventilators", "WHO", "xenophobia", "youTube", "zoonotic", "stay-at-home", "covid", "coronavirus", "hyrdoxychloroquine", "asymptomatic", "frontline", "virus", "self-isolation", "disinfectant", "shelter-in-place", "masks", "SARS-CoV-2", "ICU", "corona", "reopen", "distancing", "covering", "furlough", "tracer", "easing", "remdesivir", "mail-in", "hornet", "antibody", "in-person", "defund", "racism", "looting", "loot", "reopen", "two-metre", "pandemic", "looter", "distancing", "dexamethasone", "racial", "vaccine",
                      "curfew","johnssons","astrazeneca","hospitals","social-distance",
                      "social-distancing","police","regulations","symptoms","testing",
                      "positive-tests","negative-tests","confirmed-cases","restrictions",
                      "deaths","infected","recoveries","level","jobs","unemployed",
                      "doctors","infections","sanitise","sanitiser","sanitisation",
                      "containment")

More libraries

library(XML)
library(RCurl)
library(RColorBrewer)
library(wordcloud)

Setting up Reddit scraper

Kyle’s Reddit code that he graciously gave to me :) I attempted 2 other reddit web scraping methods for scraping comments from post but they were unsuccessful. We settled instead to just focus on the posts themselves about Covid-19 in South Africa. By scraping the r/southafrica subreddit we managed to find about 250 posts dating back to last year December which would be from when South Africa was entering harder lockdown times again. We expect that due to the fact that this is the post themselves and not the comment sof people that the sentiment would be close to neutral or will have tendencies to return to neutral if it deviates from it. We will be making use of a 7 day rolling average to see the sentiment of the reddit posts as well a smooth graph to see the tendency of the posts sentiment over time.

Reddit post data

library(RedditExtractoR)

reddit_Covid_data<-RedditExtractoR::reddit_urls(search_terms = "Covid-19", subreddit = "southafrica",page_threshold = 10)

Cleaning Reddit post data

reddit_Covid_data <- reddit_Covid_data %>%
  mutate(title = gsub(" ?(f|ht)tp(s?)://(.*)[.][a-z]+", "", title ),
         title  = gsub("&amp", "", title ),
         title  = gsub("(RT|via)((?:\\b\\W*@\\w+)+)", "", title ),
         title = gsub("@\\w+", "", title ),
         title  = gsub("[[:punct:]]", "", title ),
         title  = gsub("[[:digit:]]", "", title ),
         title  = gsub("http\\w+", "", title ),
         title  = gsub("[ \t]{2,}", "", title ),
         title  = gsub("^\\s+|\\s+$", "", title ),
         title  = gsub("&amp", "", title )) %>%
  mutate(title  = str_replace_all(title ," "," "),
         title  = str_replace_all(title ,"RT @[a-z,A-Z]*: "," "),
         title  = str_replace_all(title ,"#[a-z,A-Z]*"," "),
         title  = str_replace_all(title ,"@[a-z,A-Z]*"," "))
write_csv(reddit_Covid_data,"data_in/reddit_SA.csv")

reddit_Covid_data$date= dmy(reddit_Covid_data$date)
reddit_Covid_data<- reddit_Covid_data %>% mutate("X1"=row_number())

Sentiment of reddit posts using SentimentR

sd<- get_sentences(reddit_Covid_data$title)
reddit_sentiment<- sentiment(sd)

reddit_sentiment<- left_join(reddit_Covid_data,reddit_sentiment,
                             by=c("X1"="element_id"))

Modeling Reddit sentiment over time

ggplot(data=reddit_sentiment, aes(x=date, y=rollmean(sentiment, 30,  na.pad=TRUE))) +
       geom_line(color="pink", size=.5)+
  geom_smooth() +
  theme_minimal()+
  scale_y_continuous(expand = c(0,0), breaks = c(-0.4,-0.2,0,0.2,0.4)) +
  ylim(c(-0.4, 0.4))+
  labs(title = "Sentiment from the titles of Reddit post about Covid in SA", x="Date", 
       y="Sentiment")

As can be seen from the graph the sentiment of the posts started out more negative and that would correlated to be around to higher infections per day. The sentiment does have a positive trend towards the end of the wave of infections. Even though there is very slight fluctuations the posts seem mostly neutral.

What follows is the modeling of the comment sections of many of the posts we found. The Reddit hole of comments. All who enter, beware! Here we create a dataframe from comments made by users on posts that have the topic of Covid-19

library(rtweet)
library(ggplot2)
library(tidyr)
library(dplyr)

Attaching package: ‘dplyr’

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
library(tidytext)
library(stringr)
library(scales)
library(readr)

Attaching package: ‘readr’

The following object is masked from ‘package:scales’:

    col_factor
library(lubridate)

Attaching package: ‘lubridate’

The following objects are masked from ‘package:base’:

    date, intersect, setdiff, union
library(vader)
library(topicmodels)
library(quanteda)
Package version: 3.0.0
Unicode version: 13.0
ICU version: 69.1
Parallel computing: 8 of 8 threads used.
See https://quanteda.io for tutorials and examples.
library(lubridate)
library(zoo)

Attaching package: ‘zoo’

The following object is masked from ‘package:quanteda’:

    index

The following objects are masked from ‘package:base’:

    as.Date, as.Date.numeric
library(plotly)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio

Attaching package: ‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout
library(forcats)
library(igraph)

Attaching package: ‘igraph’

The following object is masked from ‘package:plotly’:

    groups

The following objects are masked from ‘package:lubridate’:

    %--%, union

The following objects are masked from ‘package:dplyr’:

    as_data_frame, groups, union

The following object is masked from ‘package:tidyr’:

    crossing

The following objects are masked from ‘package:stats’:

    decompose, spectrum

The following object is masked from ‘package:base’:

    union
library(ggraph)
library(widyr)
library(qdapRegex)

Attaching package: ‘qdapRegex’

The following object is masked from ‘package:dplyr’:

    explain

The following object is masked from ‘package:ggplot2’:

    %+%
library(magick)
Linking to ImageMagick 6.9.12.3
Enabled features: cairo, fontconfig, freetype, heic, lcms, pango, raw, rsvg, webp
Disabled features: fftw, ghostscript, x11

Here we found a way to get the comment of the Reddit posts that were modeled earlier.


comments<- get_reddit(search_terms = "Covid-19", subreddit = "southafrica", page_threshold = 5,
                      sort_by = "new")
write_csv(comments, "data_in/reddit_comments.csv")

We first clean the original text to remove links, punctuation, digits, links, @’s. Then we tokenize the comments and remove stop words from tidytext and our own stopword dictionary. We also use the “twitter” token to handle any left over @’s and URLS.

From our tidied comment dataset, we look for the top words that appear. This will give us a good idea of what most people comment about. We find that most people talk about other people usually in conjunction with other words like vaccines or covid.

#top words
top_words <- tidy_reddit_df %>%
  anti_join(stop_words) %>%
  count(word) %>%
  arrange(desc(n))
Joining, by = "word"
top_words %>%
  slice(1:20) %>%
  ggplot(aes(reorder(word,-n), n, fill = word)) +
  geom_bar(stat = "identity") +
  theme_minimal() +
  theme(
    axis.text.x = element_text(
      angle = 60,
      hjust = 1,
      size = 13
    ),
    plot.title = element_text(hjust = 0.5, size = 18)
  ) +
  ylab("Frequency") +
  xlab ("") +
  ggtitle("Most frequent words used in reddit comments") +
  guides(fill = FALSE)
Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.

After changing, adding, and removing terms from the filters, we can conclude that the tf-idf anaylsis is not useful for these comments. The simple amount of comment data per post and the fact that the time frames are sporadic make that you are unable to . When tf-idf runs, it increases their term weights as they are “unique” because they are not found among other media agencies. These words are usually not telling. What it can tell us - which segments these media agencies post about the most.

#tf-idf
tidy_reddit_tf_idf <- tidy_reddit_df %>%
  select(author, word) %>%
  group_by(author) %>%
  count(word, author) %>%
  bind_tf_idf(word, author, n)

#calculate a frequency for each agency and word
frequency <- tidy_reddit_tf_idf %>%
  group_by(author) %>%
  count(word, sort = TRUE) %>%
  left_join(tidy_reddit_df %>%
              group_by(author) %>%
              summarise(total = n())) %>%
  mutate(freq = n / total)
Joining, by = "author"
tidy_reddit_tf_idf %>%
  group_by(author) %>%
  slice_max(tf_idf, n = 15) %>%
  ungroup() %>%
  ggplot(aes(tf_idf, fct_reorder(word, tf_idf), fill = author)) +
  geom_col(show.legend = FALSE) +
  facet_wrap(~ author, ncol = 2, scales = "free") +
  labs(x = "tf-idf", y = NULL)

By modeling bigrams and trigrams for our dataset gives us a better understanding of what topic is being discussed with each word. We can then also see which sentiments are incorrectly labeled. “not good” gives better context of a negative sentiment, rather than it being incorrectly identified as positive good. Although this works really well for Twitter, it does not seems to carry through that well to the point of interpretation for Reddit data.

#bigrams
tidy_bigram_df <- reddit_comments_df %>%
  #filter(str_detect(text, fixed(covid_dictionary, ignore_case = TRUE))) %>%
  filter(!str_detect(comment, "^RT")) %>%
  mutate(comment = gsub(" ?(f|ht)tp(s?)://(.*)[.][a-z]+", " ", comment)) %>%
  unnest_tokens(bigram, comment, token = "ngrams", n = 2) %>%
  separate(bigram, c("word1", "word2"), sep = " ")

bigrams_filtered <- tidy_bigram_df %>%
  filter(!word1 %in% stop_words$word) %>%
  filter(!word2 %in% stop_words$word)

# new bigram counts:
bigram_counts <- bigrams_filtered %>%
  count(word1, word2, sort = TRUE)

bigrams_united <- bigrams_filtered %>%
  unite(bigram, word1, word2, sep = " ")

#tf-idf bigrams
bigram_tf_idf <- bigrams_united %>%
  count(author, bigram) %>%
  bind_tf_idf(bigram, author, n) %>%
  arrange(desc(tf_idf))

bigram_tf_idf %>%
  group_by(author) %>%
  slice_max(tf_idf, n = 15) %>%
  ungroup() %>%
  ggplot(aes(tf_idf, fct_reorder(bigram, tf_idf), fill = author)) +
  geom_col(show.legend = FALSE) +
  facet_wrap( ~ author, ncol = 2, scales = "free") +
  labs(x = "tf-idf", y = NULL)


#weights and graphs
bigram_graph <- bigram_counts %>%
  filter(n > 100) %>%
  graph_from_data_frame()

set.seed(1234)
a <- grid::arrow(type = "closed", length = unit(.15, "inches"))
ggraph(bigram_graph, layout = "fr") +
  geom_edge_link(
    aes(edge_alpha = n),
    show.legend = FALSE,
    arrow = a,
    end_cap = circle(.07, 'inches')
  ) +
  geom_node_point(color = "lightblue", size = 5) +
  geom_node_text(aes(label = name),
                 vjust = 1,
                 hjust = 1,
                 repel = TRUE) +
  theme_void()
Don't know how to automatically pick scale for object of type function. Defaulting to continuous.
Error: Aesthetics must be valid data columns. Problematic aesthetic(s): edge_alpha = n. 
Did you mistype the name of a data column or forget to add after_stat()?
Run `rlang::last_error()` to see where the error occurred.

We give more weight to words that appear more often with the incorrect sentiment. We can now reverse the sentiment of these words once VADER has been run on the dataset.

#vader lexicon imported from VADER GitHub
vader_lexicon <- read_csv2("data_in/vader_lexicon.csv") %>%
  rename("word" = TOKEN, "value" = `MEAN-SENTIMENT-RATING`)
ℹ Using "','" as decimal and "'.'" as grouping mark. Use `read_delim()` for more control.

── Column specification ─────────────────────────────────────────────────────────────────────
cols(
  TOKEN = col_character(),
  `MEAN-SENTIMENT-RATING` = col_character(),
  `STANDARD DEVIATION` = col_character(),
  `RAW-HUMAN-SENTIMENT-RATINGS` = col_character()
)
#common negation words
negation_words <-
  c(
    "not",
    "no",
    "never",
    "without",
    "no",
    "not",
    "none",
    "no one",
    "nobody",
    "nothing",
    "neither",
    "nowhere",
    "never",
    "doesn’t",
    "isn’t",
    "wasn’t",
    "shouldn’t",
    "wouldn’t",
    "couldn’t",
    "won’t",
    "can’t",
    "don’t"
  )
negated_words <- tidy_bigram_df %>%
  filter(word1 %in% fixed(negation_words, ignore_case = TRUE)) %>%
  inner_join(vader_lexicon, by = c(word2 = "word")) %>%
  mutate(value = as.double(value)) %>%
  count(word1, word2, value, sort = TRUE) %>%
  mutate(contribution = n * value) %>%
  arrange(desc(abs(contribution))) %>%
  mutate(word2 = reorder(word2, contribution))
negated_words %>%
  head(40) %>%
  ggplot(aes(n * value, word2, fill = n * value > 0)) +
  geom_col(show.legend = FALSE) +
  facet_wrap( ~ word1, scales = "free_y") +
  labs(x = "Sentiment value * # number of occurrences",
       y = "Words preceded by negation terms")

The graph below shows which words are most likely to co-occur. We use this to understand the context of words in our topic modelling.

reddit_comments_section_words <- tidy_reddit_df %>%
  mutate(section = row_number() %/% 10) %>%
  filter(section > 0)

# count words co-occuring within sections
word_pairs <- reddit_comments_section_words %>%
  pairwise_count(word, section, sort = TRUE)

# we need to filter for at least relatively common words first
word_cors <- reddit_comments_section_words %>%
  group_by(word) %>%
  filter(n() >= 20) %>%
  pairwise_cor(word, section, sort = TRUE)%>%
  filter(correlation>=.05)
   
  

# Correlation of next word
# word_cors %>%
#   filter(item1 == "vaccine")

word_cors %>%
  filter(item1 %in% c("covid", "vaccine", "lockdown", "zuma", "gauteng", "ramaphosa")) %>%
  group_by(item1) %>%
  slice_max(correlation, n = 6) %>%
  ungroup() %>%
  mutate(item2 = reorder(item2, correlation)) %>%
  ggplot(aes(item2, correlation)) +
  geom_bar(stat = "identity") +
  facet_wrap( ~ item1, scales = "free") +
  coord_flip() 

  

set.seed(1234)
word_cors %>%
  graph_from_data_frame() %>%
  ggraph(layout = "fr") +
  geom_edge_link(aes(edge_alpha = correlation),
                 show.legend = FALSE,
                 edge_width = 3) +
  geom_node_point(color = "lightblue", size = 5) +
  geom_node_text(aes(label = name), repel = TRUE) +
  theme_void()

What we noticed here is that alot of the data is difficult to model due to the size and the amount of different posts. What we can however see is that more recent tweets seem to have a more negative compound sentiment value than tweets from earlier this year.

#vader_df <- vader_df(reddit_comments_df$comment)
#write_as_csv(vader_df, "data_in/vader_reddit_comments")

 

vader_df <- read_csv("data_in/vader_reddit_comments.csv")

── Column specification ─────────────────────────────────────────────────────────────────────
cols(
  text = col_character(),
  word_scores = col_character(),
  compound = col_double(),
  pos = col_double(),
  neu = col_double(),
  neg = col_double(),
  but_count = col_double()
)
vader_df <- vader_df %>% mutate("X1" = row_number())
reddit_comments_df <- reddit_comments_df %>% mutate("X1" = row_number())
reddit_comments_vader <- reddit_comments_df %>% left_join(vader_df, by = "X1")

#General sentiment over time. Media agencies seem to have an even number of positive and negative tweets per day.
ggplot(
  reddit_comments_vader %>%
    mutate(post_date = as.Date(post_date)) %>%
    group_by(post_date, author) %>%
    mutate(compound = replace(compound, is.na(compound), 0)) %>%
    summarise(sum_compound = sum(as.double(compound))),
  aes(post_date, sum_compound, fill = author)
) +
  geom_bar(stat = "identity") +
  geom_smooth(method = "lm", na.rm = TRUE, se = FALSE) +
  facet_wrap( ~ author, scales = "free_x", ncol = 2) +
  theme_minimal() +
  scale_y_continuous(expand = c(0, 0)) +
  scale_x_date(date_breaks = "3 day", date_labels = "%m-%d") +
  theme(
    axis.text.x = element_text(
      angle = 90,
      vjust = 0.5,
      hjust = 1
    ),
    panel.grid.minor.y = element_blank(),
    panel.grid.minor.x = element_blank(),
  )
`summarise()` has grouped output by 'post_date'. You can override using the `.groups` argument.
`geom_smooth()` using formula 'y ~ x'

ggplot(
  reddit_comments_vader %>%
    mutate(post_date = as.Date(post_date)) %>%
    group_by(post_date) %>%
    filter(author == "angel_yellow_brick") %>%
    summarise(compound),
  aes(post_date, compound)
) +
  geom_bar(stat = "identity") +
  geom_smooth(method = "lm", na.rm = TRUE) +
  theme_minimal() +
  scale_y_continuous(expand = c(0, 0))
`summarise()` has grouped output by 'post_date'. You can override using the `.groups` argument.
`geom_smooth()` using formula 'y ~ x'

#News sentiment
reddit_comments_vader %>%
  mutate(post_date = as.Date(post_date)) %>%
  group_by(post_date, author) %>%
  summarise(compound) %>%
  arrange(desc(compound))
`summarise()` has grouped output by 'post_date', 'author'. You can override using the `.groups` argument.
ggplot(reddit_comments_vader %>% arrange(compound) %>% mutate(X1 = factor(X1, levels = X1)),
       aes(x = X1)) +
  geom_point(mapping =  aes(y = compound)) +
  theme_minimal() +
  scale_y_continuous(expand = c(0, 0))
Warning: Removed 6 rows containing missing values (geom_point).

reddit_comments_vader%>%
  mutate(post_date = as.Date(post_date, format = "%d-%m-%y")) %>%
  group_by(post_date, author) %>%
  mutate(compound = replace(compound, is.na(compound), 0)) %>%
  summarise(sum_compound = sum(as.double(compound)))
`summarise()` has grouped output by 'post_date'. You can override using the `.groups` argument.

The plot below maps the average total comments on a post per day.

Our main topic influence is COVID-19 as this is what currently affects the country the most. We based our data collection around the word COVID-19 and expect to see a lot of inter related terms about it spread throughout the different topics. As you can see, due to the fact that the posts were all about Covid, the comments all inherited the overarching topic.

tidy_matrix <-
  tidy_reddit_df %>% sample(tidy_reddit_df, size=0.1) %>% count(author, word) %>% cast_dfm(author, word, n)
Error in FUN(left) : invalid argument type

We determine the correct number of topics in mechanisms like the LDA (Latent Dirichlet Allocation) as they determine the quality of features of the words.

A topic model is a type of statistic model for discovering the abstract “topics” that occur in a collection of documents.

Topic modeling is used to classify and retrieve information. These models capture word correlations in a collection of textual documents with topics. It is very difficult to pick the right number of topics for a specific dataset. It is important to determine the value of ‘k’.

The importance of the value of ‘k’ is to ensure you do not over estimate or underestimate the data. If you over estimate it, you will be left with topics that carry very little meaning and if you under estimate the data, you will lose out on topics that could have been useful to your research.

By looking at the lowest minimum and the highest maximum, we can determine the ‘k’. This is how we have interpreted the graphs produced. Griffiths2004 is not informative in this situation and is therefore ignore

This method used has been proved to produce the best results of LDA without having to manually tune the ‘k’ value.

library("ldatuning")
library("topicmodels")

data("AssociatedPress", package = "topicmodels")
dtm <- AssociatedPress[1:10,]

result <- FindTopicsNumber(
  tidy_matrix,
  topics = seq(from = 2, to = 15, by = 1),
  metrics = c("Griffiths2004", "CaoJuan2009", "Arun2010", "Deveaud2014"),
  method = "Gibbs",
  control = list(seed = 77),
  mc.cores = 2L,
  verbose = TRUE
)
fit models... done.
calculate metrics:
  Griffiths2004...
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQpSZWFzb25zIGZvciB0aGUgbWVkaWEgc291cmNlcyBjaG9zZW46Ck5ld3MgMjQgOiBSZWNvZ25pemVkIGJ5IEFQUCBBbm5pZSAoQXBwIEFubmllIGlzIHRoZSBzdGFuZGFyZCBpbiBhcHAgYW5hbHl0aWNzIGFuZCBhcHAgbWFya2V0IGRhdGEpIGFzIHRoZSBtb3N0IGtub3duIFNvdXRoIEFmcmljYW4gaW50ZXJuZXQgbWVkaWEgc291cmNlLiAoQ2hpbmVzZSBBY2FkZW15IG9mIEN5YmVyc3BhY2UgU3R1ZGllc3B1Ymxpc2hlcj1TcHJpbmdlciAoMTUgU2VwdGVtYmVyIDIwMTgpLiBXb3JsZCBJbnRlcm5ldCBEZXZlbG9wbWVudCBSZXBvcnQgMjAxNzogVHJhbnNsYXRlZCBieSBQZW5nIFBpbmcuIHAuIDIwMy4gSVNCTiA5NzgzNjYyNTc1MjQ2LiBPQ0xDIDEwNTI3NjY1MDguKQoKVGltZXMgTGl2ZSA6IENsYWltIHRvIGJlIFNvdXRoIEFmcmljYSdzIHNlY29uZC1iaWdnZXN0IG5ld3Mgd2Vic2l0ZSwgcHVibGlzaGVkIGJ5IEFyZW5hIEhvbGRpbmdzIChUaW1lcyBMaXZlIHdlYnNpdGUpLiBObyBldmlkZW5jZSBmb3VuZCB0byBkaXNwcm92ZSB0aGlzIGNsYWltLiBJbiB0b3AgMTAgb2YgbW9zdCB2aXNpdGVkIHB1YmxpY2F0aW9uIHdlYnNpdGVzIGZvciBTb3V0aCBBZnJpY2EuCgpFV04gOiBOb3QgbXVjaCBpbmZvIGJ1dCBpdCBjYW4gYmUgY29uc2lkZXJlZCB0byBiZSBwb3B1bGFyIGJlY2F1c2UgaXQgb3JpZ2luYXRlZCBmcm9tIDIgcmFkaW8gc3RhdGlvbnMgKEtGTSBhbmQgQ2FwZVRhbGspLCBNYWtlcyBpdCBhIHBvcHVsYXIgYW5kIHBlb3BsZSBoZWFyIGFib3V0IGl0IHdpdGhvdXQgYWN0aXZlbHkgaGF2aW5nIHRvIGdvIGFuZCBzZWFyY2ggZm9yIHRoZSBuZXdzIGFnZW5jeSB0aGVtc2VsdmVzLiBJbiB0b3AgMTAgb2YgbW9zdCB2aXNpdGVkIHB1YmxpY2F0aW9uIHdlYnNpdGVzIGZvciBTb3V0aCBBZnJpY2EuCgplTkNBOiBOb3QgbXVjaCBpbmZvIGJ1dCBzZWVtcyBwb3B1bGFyLiBVc2VkIHRvIEUgTmV3cyBmcm9tIFRWIGNoYW5uZWwuIE1pZ2h0IG5vdCBiZSBhcyB0cnVzdHdvcnRoeSBhcyB0aGVyZSBoYXMgYmVlbiBjb21wbGFpbnRzIGFib3V0IHJhY2lzbSByZWNlbnRseS4gSW4gdG9wIDEwIG9mIG1vc3QgdmlzaXRlZCBwdWJsaWNhdGlvbiB3ZWJzaXRlcyBmb3IgU291dGggQWZyaWNhLgoKU0FCQzogTmF0aW9uYWwgbmV3cyBjb21wYW55IHdpdGggZ292ZXJubWVudCB0aWVzLiBSZWFjaGVzIGEgd2lkZSB2YXJpZXR5IG9mIHZpZXdlcnMgaW4gZGlmZmVyZW50IGxhbmd1YWdlcy4gVGhlIGNvbXBhbnkgaXMgYm90aCBzdGF0ZSBvd25lZCBhbmQgYSBwdWJsaWMgYnJvYWRjYXN0ZXIgY29tcGFueS5odHRwczovL3d3dy5idXNpbmVzc2xpdmUuY28uemEvYmQvbmF0aW9uYWwvbWVkaWEvMjAxNS0wNS0yMC1zYWJjLWJvdGgtc3RhdGUtb3duZWQtY29tcGFueS1hbmQtcHVibGljLWJyb2FkY2FzdGVyLW1pbmlzdGVyLXNheXMvCgoKQ2hhcHRlciAxMCBvZiB0aGUgQ29uc3RpdHV0aW9uIG9mIHRoZSBSZXB1YmxpYyBvZiBTb3V0aCBBZnJpY2EsIDE5OTYgbWFrZXMgcHJvdmlzaW9uIGZvciBnb29kIGdvdmVybmFuY2Ugb2YgbmV3cyBtZWRpYSBhbmQgd2hhdCB0aGV5IHB1Ymxpc2guCgpUaGUgb3RoZXIgNCBvZiB0aGUgNSBpcyByYW5rZWQgYW1vbmcgdGhlIHRvcCAxMCBtb3N0IHZpc2l0ZWQgcHVibGljYXRpb24gc2l0ZXMgd2Vic2l0ZXMgaW4gc291dGggYWZyaWNhIGFzIGZvdW5kIGJ5IApodHRwczovL215YnJvYWRiYW5kLmNvLnphL25ld3MvaW50ZXJuZXQvMzU4NDUzLWhlcmUtYXJlLXNvdXRoLWFmcmljYXMtbW9zdC1wb3B1bGFyLW5ld3Mtd2Vic2l0ZXMuaHRtbC4KVGhlc2Ugc2l0ZXMgYXJlIHRoZSBmaXJzdCBzaXRlcyBvbiB0aGUgdG9wIDEwIGxpc3Qgb2YgcHVibGljYXRpb24gc2l0ZXMgdGhhdCBpbmNsdWRlIGdlbmVyYWwgbmV3cyBhbG9uZyB3aXRoIG5ld3MgYWJvdXQgY292aWQtMTkgdGhhdCBkbyBub3QgaGF2ZSBtYWpvciBoaXN0b3JpY2FsIGlzc3VlcyB0aGF0IGNvdWxkIGJyaW5nIHRoZWlyIGNyZWRpYmlsaXR5IGluIHF1ZXN0aW9uLgpSZWFzb25zIHRoYXQgb3RoZXIgbmV3cyBvciBwdWJsaXNoaW5nIHNvdXJjZXMgdGhhdCBhcmUgcmFua2VkIGhpZ2hlciB3ZXJlIG5vdCB1c2VkIGlzIGR1ZSB0byB0aGUgZmFjdCB0aGF0IHRoZXNlIHNvdXJjZXMgZWl0aGVyIG9ubHkgZm9jdXMgb24gc3BlY2lmaWMgbmV3cyBsaWtlIG5ldyB0ZWNobm9sb2d5IG9yIGZpbmFuY2lhbCBhc3BlY3RzLCBvciB0aGVzZSBzb3VyY2VzIGFyZSBub3QgYXMgcG9wdWxhciB0aHJvdWdob3V0IHRoZSB3aG9sZSBvZiBTb3V0aCBBZnJpY2EuCgoKCkltcG9ydGluZyBMaWJyYXJpZXMKYGBge3J9CmxpYnJhcnkodGlkeXRleHQpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHRleHRkYXRhKQpsaWJyYXJ5KHNlbnRpbWVudHIpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShzdHJpbmdpKQpsaWJyYXJ5KHJ0d2VldCkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHNjYWxlcykKbGlicmFyeShyZWFkcikKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkodG9waWNtb2RlbHMpCmxpYnJhcnkocXVhbnRlZGEpCmxpYnJhcnkocmVzaGFwZTIpCmxpYnJhcnkoem9vKQpgYGAKSW1wb3J0aW5nIGRhdGEgb2YgY29sbGVjdGVkIHR3ZWV0cy4gVGhpcyB3YXMgZG9uZSB0byBzZWUgd2hpY2ggbGV4aWNvbiB3b3JrcyBiZXN0IGJldHdlZW4gVkFERVIgYW5kIFNlbnRpbWVudFIKYGBge3J9Cm1lZGlhX2FnZW5jeV9kZiA8LSByZWFkX2NzdigiZGF0YV9pbi9tZWRpYV9hZ2VuY3lfdHdlZXRzLmNzdiIpCm1lZGlhX2FnZW5jeV9kZiA8LSBtZWRpYV9hZ2VuY3lfZGZbICwgY29sU3Vtcyhpcy5uYShtZWRpYV9hZ2VuY3lfZGYpKSA8IG5yb3cobWVkaWFfYWdlbmN5X2RmKV0KbWVkaWFfYWdlbmN5X2RmIDwtIG1lZGlhX2FnZW5jeV9kZiAlPiUgbXV0YXRlKCJYMSIgPSByb3dfbnVtYmVyKCkpCmBgYAoKV3JhbmdlbGluZyBhbmQgY2xlYW5pbmcgZGF0YQpgYGB7cn0KI0NsZWFuaW5nIGRhdGEKbWVkaWFfYWdlbmN5X2RmIDwtIG1lZGlhX2FnZW5jeV9kZiAlPiUKICBtdXRhdGUodGV4dCA9IGdzdWIoIiA/KGZ8aHQpdHAocz8pOi8vKC4qKVsuXVthLXpdKyIsICIiLCB0ZXh0KSwKICAgICAgICAgdGV4dCA9IGdzdWIoIiZhbXAiLCAiIiwgdGV4dCksCiAgICAgICAgIHRleHQgPSBnc3ViKCIoUlR8dmlhKSgoPzpcXGJcXFcqQFxcdyspKykiLCAiIiwgdGV4dCksCiAgICAgICAgIHRleHQgPSBnc3ViKCJAXFx3KyIsICIiLCB0ZXh0KSwKICAgICAgICAgdGV4dCA9IGdzdWIoIltbOnB1bmN0Ol1dIiwgIiIsIHRleHQpLAogICAgICAgICB0ZXh0ID0gZ3N1YigiW1s6ZGlnaXQ6XV0iLCAiIiwgdGV4dCksCiAgICAgICAgIHRleHQgPSBnc3ViKCJodHRwXFx3KyIsICIiLCB0ZXh0KSwKICAgICAgICAgdGV4dCA9IGdzdWIoIlsgXHRdezIsfSIsICIiLCB0ZXh0KSwKICAgICAgICAgdGV4dCA9IGdzdWIoIl5cXHMrfFxccyskIiwgIiIsIHRleHQpLAogICAgICAgICB0ZXh0ID0gZ3N1YigiJmFtcCIsICIiLCB0ZXh0KSkgJT4lCiAgbXV0YXRlKHRleHQgPSBzdHJfcmVwbGFjZV9hbGwodGV4dCwiICIsIiAiKSwKICAgICAgICAgdGV4dCA9IHN0cl9yZXBsYWNlX2FsbCh0ZXh0LCJSVCBAW2EteixBLVpdKjogIiwiICIpLAogICAgICAgICB0ZXh0ID0gc3RyX3JlcGxhY2VfYWxsKHRleHQsIiNbYS16LEEtWl0qIiwiICIpLAogICAgICAgICB0ZXh0ID0gc3RyX3JlcGxhY2VfYWxsKHRleHQsIkBbYS16LEEtWl0qIiwiICIpKQoKCiN0aWR5aW5nIGRhdGEKdGlkeV9jb3ZpZF9tZWRpYV9kZiA8LSBtZWRpYV9hZ2VuY3lfZGYgJT4lCiAgI2ZpbHRlcihzdHJfZGV0ZWN0KHRleHQsIGZpeGVkKGNvdmlkX2RpY3Rpb25hcnksIGlnbm9yZV9jYXNlID0gVFJVRSkpKSAlPiUKICBmaWx0ZXIoIXN0cl9kZXRlY3QodGV4dCwgIl5SVCIpKSAlPiUKICBtdXRhdGUodGV4dCA9IGdzdWIoIiA/KGZ8aHQpdHAocz8pOi8vKC4qKVsuXVthLXpdKyIsICIiLCB0ZXh0KSkgJT4lCiAgdW5uZXN0X3Rva2Vucyh3b3JkLCB0ZXh0LCB0b2tlbiA9ICJ0d2VldHMiKSAlPiUKICBmaWx0ZXIoIXdvcmQgJWluJSBzdG9wX3dvcmRzJHdvcmQsCiAgICAgICAgICF3b3JkICVpbiUgc3RyX3JlbW92ZV9hbGwoc3RvcF93b3JkcyR3b3JkLCAiJyIpLAogICAgICAgICBzdHJfZGV0ZWN0KHdvcmQsICJbYS16XSIpLAogICAgICAgICAhKHdvcmQgPT0iI3NhYmNuZXdzIiB8CiAgICAgICAgICAgICB3b3JkID09IiNlbmNhIiB8CiAgICAgICAgICAgICB3b3JkID09Imh0dHBzIiB8CiAgICAgICAgICAgICB3b3JkID09IiNkc3R2NDAzIiB8CiAgICAgICAgICAgICB3b3JkID09InQuY28iIHwKICAgICAgICAgICAgIHdvcmQgPT0icnQiIHwKICAgICAgICAgICAgIHdvcmQgPT0iYW1wIikpCgpgYGAKYGBge3J9CiNmaW5kaW5nIHRoZSBzY3JlZW4gbmFtZXMgb2YgbWVkaWEgYW5nZW5jaWVzCmFnZW5jaWVzPC0gbWVkaWFfYWdlbmN5X2RmICU+JQogIHNlbGVjdChzY3JlZW5fbmFtZSkgCmFnZW5jaWVzICU+JQogIGRpc3RpbmN0KHNjcmVlbl9uYW1lKQpgYGAKClNlbmltZW50IEFuYWx5c2lzIHdpdGggU2VudGltZW50UgpgYGB7cn0KCm15dGV4dDwtIG1lZGlhX2FnZW5jeV9kZiAKCm15dGV4dCA8LSBnZXRfc2VudGVuY2VzKG15dGV4dCR0ZXh0KQpzcl9kYXRhIDwtc2VudGltZW50KG15dGV4dCkKI3dyaXRlX2Nzdihzcl9kYXRhLCJkYXRhX2luL3NlbnRpbWVudHJfZGF0YS5jc3YiKQpgYGAKQWRkaW5nIHRpbWUgZGF0YSB0byBzZW50aW1lbnQgZGYKYGBge3J9CnRpbWVfZGF0YSA8LSBtZWRpYV9hZ2VuY3lfZGYgJT4lCiAgc2VsZWN0KFgxLGNyZWF0ZWRfYXQsc2NyZWVuX25hbWUpCgpTZW50aVJfZGF0YSA8LWxlZnRfam9pbih0aW1lX2RhdGEsc3JfZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgYnk9YygiWDEiPSJlbGVtZW50X2lkIikpCiN3cml0ZV9jc3YoU2VudGlSX2RhdGEsImRhdGFfaW4vc3JfZGZfdGltZS5jc3YiKQoKYGBgCgpNb2RlbGluZyB0aGUgdGltZSBkYXRhCmBgYHtyfQojc2V0dGluZyB0aGUgZGF0ZSBmb3JtYXQKI05CIG9ubHkgcnVuIGRhdGUgZm9ybWF0IG9uY2UKU2VudGlSX2RhdGEkY3JlYXRlZF9hdCA9IHltZF9obXMoU2VudGlSX2RhdGEkY3JlYXRlZF9hdCkKI2ZpbHRlcmluZyBieSBuZXdzIGFnZW5jeQpuZXdzMjQ8LSBTZW50aVJfZGF0YSAlPiUKICBmaWx0ZXIoc2NyZWVuX25hbWU9PSJOZXdzMjQiKQoKdGltZXNfbGl2ZTwtU2VudGlSX2RhdGEgJT4lCiAgZmlsdGVyKHNjcmVlbl9uYW1lPT0iVGltZXNMSVZFIikKCmRhaWx5bWF2ZXJpY2s8LVNlbnRpUl9kYXRhICU+JQogIGZpbHRlcihzY3JlZW5fbmFtZT09ImRhaWx5bWF2ZXJpY2siKQoKc2FiYzwtU2VudGlSX2RhdGEgJT4lCiAgZmlsdGVyKHNjcmVlbl9uYW1lPT0iU0FCQ05ld3MiKQoKZU5DQTwtU2VudGlSX2RhdGEgJT4lCiAgZmlsdGVyKHNjcmVlbl9uYW1lPT0iZU5DQSIpCmBgYApHcmFwaHMgcGxvdHRpbmcgdGhlIHNlbnRpbWVudCBvZiB0aGUgZGlmZmVyZW50IG5ld3MgYWdlbmNpZXMgb3ZlciB0aW1lLiBBcyBvbmUgY2FuIHNlZSwgdGhleSBhbGwgdGVuZCB0byBtYWludGFpbiBhIG5ldXRyYWwgc3RhbmNlIHdpdGggc29tZSBmbHVjdHVhdGlvbnMgYXQgdGltZS4KYGBge3J9CiNncmFwaCBmb3IgTmV3czI0IHNlbnRpbWVudCBvdmVyIHRpbWUKZ2dwbG90KGRhdGE9bmV3czI0LCBhZXMoeD1jcmVhdGVkX2F0LCB5PXJvbGxtZWFuKHNlbnRpbWVudCwgMzAsICBuYS5wYWQ9VFJVRSkpKSArCiAgICAgICBnZW9tX2xpbmUoY29sb3I9InBpbmsiLCBzaXplPS41KSsKICBnZW9tX3Ntb290aCgpICsKICB0aGVtZV9taW5pbWFsKCkrCiAgZmFjZXRfd3JhcCh+c2NyZWVuX25hbWUpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLDApLCBicmVha3MgPSBjKC0wLjQsLTAuMiwwLDAuMiwwLjQpKSArCiAgeWxpbShjKC0wLjQsIDAuNCkpCgpgYGAKYGBge3J9CiNncmFwaCBmb3IgVGltZXMgTGl2ZSBzZW50aW1lbnQgb3ZlciB0aW1lCmdncGxvdChkYXRhPXRpbWVzX2xpdmUsIGFlcyh4PWNyZWF0ZWRfYXQsIHk9cm9sbG1lYW4oc2VudGltZW50LCAzMCwgIG5hLnBhZD1UUlVFKSkpICsKICAgICAgIGdlb21fbGluZShjb2xvcj0icGluayIsIHNpemU9LjUpKwogIGdlb21fc21vb3RoKCkgKwogIHRoZW1lX21pbmltYWwoKSsKICBmYWNldF93cmFwKH5zY3JlZW5fbmFtZSkgKwogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsMCksIGJyZWFrcyA9IGMoLTAuNCwtMC4yLDAsMC4yLDAuNCkpICsKICB5bGltKGMoLTAuNCwgMC40KSkKCgpgYGAKYGBge3J9CiNncmFwaCBmb3IgRVdOIHNlbnRpbWVudCBvdmVyIHRpbWUKZ2dwbG90KGRhdGE9ZGFpbHltYXZlcmljaywgYWVzKHg9Y3JlYXRlZF9hdCwgeT1yb2xsbWVhbihzZW50aW1lbnQsIDMwLCAgbmEucGFkPVRSVUUpKSkgKwogICAgICAgZ2VvbV9saW5lKGNvbG9yPSJwaW5rIiwgc2l6ZT0uNSkrCiAgZ2VvbV9zbW9vdGgoKSArCiAgdGhlbWVfbWluaW1hbCgpKwogIGZhY2V0X3dyYXAofnNjcmVlbl9uYW1lKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwwKSwgYnJlYWtzID0gYygtMC40LC0wLjIsMCwwLjIsMC40KSkgKwogIHlsaW0oYygtMC40LCAwLjQpKQoKCmBgYApgYGB7cn0KI2dyYXBoIGZvciBlTkNBIHNlbnRpbWVudCBvdmVyIHRpbWUKZ2dwbG90KGRhdGE9ZU5DQSwgYWVzKHg9Y3JlYXRlZF9hdCwgeT1yb2xsbWVhbihzZW50aW1lbnQsIDMwLCAgbmEucGFkPVRSVUUpKSkgKwogICAgICAgZ2VvbV9saW5lKGNvbG9yPSJwaW5rIiwgc2l6ZT0uNSkrCiAgZ2VvbV9zbW9vdGgoKSArCiAgdGhlbWVfbWluaW1hbCgpKwogIGZhY2V0X3dyYXAofnNjcmVlbl9uYW1lKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwwKSwgYnJlYWtzID0gYygtMC40LC0wLjIsMCwwLjIsMC40KSkgKwogIHlsaW0oYygtMC40LCAwLjQpKQoKCmBgYApgYGB7cn0KI2dyYXBoIGZvciBTQUJDIHNlbnRpbWVudCBvdmVyIHRpbWUKZ2dwbG90KGRhdGE9c2FiYywgYWVzKHg9Y3JlYXRlZF9hdCwgeT1yb2xsbWVhbihzZW50aW1lbnQsIDMwLCAgbmEucGFkPVRSVUUpKSkgKwogICAgICAgZ2VvbV9saW5lKGNvbG9yPSJwaW5rIiwgc2l6ZT0uNSkrCiAgZ2VvbV9zbW9vdGgoKSArCiAgdGhlbWVfbWluaW1hbCgpKwogIGZhY2V0X3dyYXAofnNjcmVlbl9uYW1lKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwwKSwgYnJlYWtzID0gYygtMC40LC0wLjIsMCwwLjIsMC40KSkgKwogIHlsaW0oYygtMC40LCAwLjQpKQoKCmBgYAoKVG9waWMgTW9kZWxsaW5nCmBgYHtyfQoKdGlkeV9tYXRyaXggPC0gdGlkeV9jb3ZpZF9tZWRpYV9kZiAlPiUgY291bnQoc2NyZWVuX25hbWUsIHdvcmQpICU+JSBjYXN0X2RmbShzY3JlZW5fbmFtZSwgd29yZCwgbikKCiAKbWVkaWFfbGRhIDwtIExEQSh0aWR5X21hdHJpeCwgayA9IDQsIGNvbnRyb2wgPSBsaXN0KHNlZWQgPSAxMjM0KSkKbWVkaWFfbGRhCm1lZGlhX3RvcGljcyA8LSB0aWR5KG1lZGlhX2xkYSwgbWF0cml4ID0gImJldGEiKQptZWRpYV90b3BpY3MKbWVkaWFfdG9wX3Rlcm1zIDwtIG1lZGlhX3RvcGljcyAlPiUKZ3JvdXBfYnkodG9waWMpICU+JQpzbGljZV9tYXgoYmV0YSwgbiA9IDEwKSAlPiUKdW5ncm91cCgpICU+JQphcnJhbmdlKHRvcGljLCAtYmV0YSkKIAoKbWVkaWFfdG9wX3Rlcm1zICU+JQptdXRhdGUodGVybSA9IHJlb3JkZXJfd2l0aGluKHRlcm0sIGJldGEsIHRvcGljKSkgJT4lCmdncGxvdChhZXMoYmV0YSwgdGVybSwgZmlsbCA9IGZhY3Rvcih0b3BpYykpKSArCmdlb21fY29sKHNob3cubGVnZW5kID0gRkFMU0UpICsKZmFjZXRfd3JhcCh+IHRvcGljLCBzY2FsZXMgPSAiZnJlZSIpICsKc2NhbGVfeV9yZW9yZGVyZWQoKQpgYGAKVmFkZXIgc3R1ZmYuIEhlcmUgd2UgY3JlYXRlZCBhIGRpY3Rpb25hcnkgd2l0aCBjb3ZpZCByZWxhdGVkIHRlcm1zIHRoYXQgYXJlIGNvbW1vbmx5IHVzZWQgdG8gaGVscCB1cyBzZWFyY2ggdGhyb3VnaCB0aGUgZGF0YWZyYW1lcyBmb3IgcmVsZXZlbnQgdHdlZXRzIGFuZCBwb3N0cy4KYGBge3J9CnZhZGVyX2RhdGE8LSByZWFkX2NzdigiZGF0YV9pbi92YWRlcl9kZi5jc3YiKQoKY292aWRfZGljdGlvbmFyeSA8LSBjKCJoZXJkIiwgImltbXVuaXR5IiwgImluY3ViYXRpb24iLCAiam9iIiwgImxvc3MiLCAiS2l0cyIsICJsb2NrZG93biIsICJtYXNrIiwgIk45NSIsICJvdXRicmVhayIsICJwYW5kZW1pYyIsICJxdWFyYW50aW5lIiwgInJlY292ZXJ5IiwgInNhbml0aXNlciIsICJ0cmFuc21pc3Npb24iLCAiVW5kZXJseWluZyIsICJjb25kaXRpb25zIiwgIlZlbnRpbGF0b3JzIiwgIldITyIsICJ4ZW5vcGhvYmlhIiwgInlvdVR1YmUiLCAiem9vbm90aWMiLCAic3RheS1hdC1ob21lIiwgImNvdmlkIiwgImNvcm9uYXZpcnVzIiwgImh5cmRveHljaGxvcm9xdWluZSIsICJhc3ltcHRvbWF0aWMiLCAiZnJvbnRsaW5lIiwgInZpcnVzIiwgInNlbGYtaXNvbGF0aW9uIiwgImRpc2luZmVjdGFudCIsICJzaGVsdGVyLWluLXBsYWNlIiwgIm1hc2tzIiwgIlNBUlMtQ29WLTIiLCAiSUNVIiwgImNvcm9uYSIsICJyZW9wZW4iLCAiZGlzdGFuY2luZyIsICJjb3ZlcmluZyIsICJmdXJsb3VnaCIsICJ0cmFjZXIiLCAiZWFzaW5nIiwgInJlbWRlc2l2aXIiLCAibWFpbC1pbiIsICJob3JuZXQiLCAiYW50aWJvZHkiLCAiaW4tcGVyc29uIiwgImRlZnVuZCIsICJyYWNpc20iLCAibG9vdGluZyIsICJsb290IiwgInJlb3BlbiIsICJ0d28tbWV0cmUiLCAicGFuZGVtaWMiLCAibG9vdGVyIiwgImRpc3RhbmNpbmciLCAiZGV4YW1ldGhhc29uZSIsICJyYWNpYWwiLCAidmFjY2luZSIsCiAgICAgICAgICAgICAgICAgICAgICAiY3VyZmV3Iiwiam9obnNzb25zIiwiYXN0cmF6ZW5lY2EiLCJob3NwaXRhbHMiLCJzb2NpYWwtZGlzdGFuY2UiLAogICAgICAgICAgICAgICAgICAgICAgInNvY2lhbC1kaXN0YW5jaW5nIiwicG9saWNlIiwicmVndWxhdGlvbnMiLCJzeW1wdG9tcyIsInRlc3RpbmciLAogICAgICAgICAgICAgICAgICAgICAgInBvc2l0aXZlLXRlc3RzIiwibmVnYXRpdmUtdGVzdHMiLCJjb25maXJtZWQtY2FzZXMiLCJyZXN0cmljdGlvbnMiLAogICAgICAgICAgICAgICAgICAgICAgImRlYXRocyIsImluZmVjdGVkIiwicmVjb3ZlcmllcyIsImxldmVsIiwiam9icyIsInVuZW1wbG95ZWQiLAogICAgICAgICAgICAgICAgICAgICAgImRvY3RvcnMiLCJpbmZlY3Rpb25zIiwic2FuaXRpc2UiLCJzYW5pdGlzZXIiLCJzYW5pdGlzYXRpb24iLAogICAgICAgICAgICAgICAgICAgICAgImNvbnRhaW5tZW50IikKCmBgYAoKCk1vcmUgbGlicmFyaWVzCmBgYHtyfQpsaWJyYXJ5KFhNTCkKbGlicmFyeShSQ3VybCkKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkod29yZGNsb3VkKQpgYGAKU2V0dGluZyB1cCBSZWRkaXQgc2NyYXBlcgoKS3lsZSdzIFJlZGRpdCBjb2RlIHRoYXQgaGUgZ3JhY2lvdXNseSBnYXZlIHRvIG1lIDopCkkgYXR0ZW1wdGVkIDIgb3RoZXIgcmVkZGl0IHdlYiBzY3JhcGluZyBtZXRob2RzIGZvciBzY3JhcGluZyBjb21tZW50cyBmcm9tIHBvc3QgYnV0IHRoZXkgd2VyZSB1bnN1Y2Nlc3NmdWwuIFdlIHNldHRsZWQgaW5zdGVhZCB0byBqdXN0IGZvY3VzIG9uIHRoZSBwb3N0cyB0aGVtc2VsdmVzIGFib3V0IENvdmlkLTE5IGluIFNvdXRoIEFmcmljYS4KQnkgc2NyYXBpbmcgdGhlIHIvc291dGhhZnJpY2Egc3VicmVkZGl0IHdlIG1hbmFnZWQgdG8gZmluZCBhYm91dCAyNTAgcG9zdHMgZGF0aW5nIGJhY2sgdG8gbGFzdCB5ZWFyIERlY2VtYmVyIHdoaWNoIHdvdWxkIGJlIGZyb20gd2hlbiBTb3V0aCBBZnJpY2Egd2FzIGVudGVyaW5nIGhhcmRlciBsb2NrZG93biB0aW1lcyBhZ2Fpbi4gV2UgZXhwZWN0IHRoYXQgZHVlIHRvIHRoZSBmYWN0IHRoYXQgdGhpcyBpcyB0aGUgcG9zdCB0aGVtc2VsdmVzIGFuZCBub3QgdGhlIGNvbW1lbnQgc29mIHBlb3BsZSB0aGF0IHRoZSBzZW50aW1lbnQgd291bGQgYmUgY2xvc2UgdG8gbmV1dHJhbCBvciB3aWxsIGhhdmUgdGVuZGVuY2llcyB0byByZXR1cm4gdG8gbmV1dHJhbCBpZiBpdCBkZXZpYXRlcyBmcm9tIGl0LiBXZSB3aWxsIGJlIG1ha2luZyB1c2Ugb2YgYSA3IGRheSByb2xsaW5nIGF2ZXJhZ2UgIHRvIHNlZSB0aGUgc2VudGltZW50IG9mIHRoZSByZWRkaXQgcG9zdHMgYXMgd2VsbCBhIHNtb290aCBncmFwaCB0byBzZWUgdGhlIHRlbmRlbmN5IG9mIHRoZSBwb3N0cyBzZW50aW1lbnQgb3ZlciB0aW1lLgoKUmVkZGl0IHBvc3QgZGF0YQpgYGB7ciBSZXRyaWV2aW5nIHRoZSBSZWRkaXQgcG9zdCBkYXRhfQpsaWJyYXJ5KFJlZGRpdEV4dHJhY3RvUikKCnJlZGRpdF9Db3ZpZF9kYXRhPC1SZWRkaXRFeHRyYWN0b1I6OnJlZGRpdF91cmxzKHNlYXJjaF90ZXJtcyA9ICJDb3ZpZC0xOSIsIHN1YnJlZGRpdCA9ICJzb3V0aGFmcmljYSIscGFnZV90aHJlc2hvbGQgPSAxMCkKYGBgCgpDbGVhbmluZyBSZWRkaXQgcG9zdCBkYXRhCmBgYHtyfQpyZWRkaXRfQ292aWRfZGF0YSA8LSByZWRkaXRfQ292aWRfZGF0YSAlPiUKICBtdXRhdGUodGl0bGUgPSBnc3ViKCIgPyhmfGh0KXRwKHM/KTovLyguKilbLl1bYS16XSsiLCAiIiwgdGl0bGUgKSwKICAgICAgICAgdGl0bGUgID0gZ3N1YigiJmFtcCIsICIiLCB0aXRsZSApLAogICAgICAgICB0aXRsZSAgPSBnc3ViKCIoUlR8dmlhKSgoPzpcXGJcXFcqQFxcdyspKykiLCAiIiwgdGl0bGUgKSwKICAgICAgICAgdGl0bGUgPSBnc3ViKCJAXFx3KyIsICIiLCB0aXRsZSApLAogICAgICAgICB0aXRsZSAgPSBnc3ViKCJbWzpwdW5jdDpdXSIsICIiLCB0aXRsZSApLAogICAgICAgICB0aXRsZSAgPSBnc3ViKCJbWzpkaWdpdDpdXSIsICIiLCB0aXRsZSApLAogICAgICAgICB0aXRsZSAgPSBnc3ViKCJodHRwXFx3KyIsICIiLCB0aXRsZSApLAogICAgICAgICB0aXRsZSAgPSBnc3ViKCJbIFx0XXsyLH0iLCAiIiwgdGl0bGUgKSwKICAgICAgICAgdGl0bGUgID0gZ3N1YigiXlxccyt8XFxzKyQiLCAiIiwgdGl0bGUgKSwKICAgICAgICAgdGl0bGUgID0gZ3N1YigiJmFtcCIsICIiLCB0aXRsZSApKSAlPiUKICBtdXRhdGUodGl0bGUgID0gc3RyX3JlcGxhY2VfYWxsKHRpdGxlICwiICIsIiAiKSwKICAgICAgICAgdGl0bGUgID0gc3RyX3JlcGxhY2VfYWxsKHRpdGxlICwiUlQgQFthLXosQS1aXSo6ICIsIiAiKSwKICAgICAgICAgdGl0bGUgID0gc3RyX3JlcGxhY2VfYWxsKHRpdGxlICwiI1thLXosQS1aXSoiLCIgIiksCiAgICAgICAgIHRpdGxlICA9IHN0cl9yZXBsYWNlX2FsbCh0aXRsZSAsIkBbYS16LEEtWl0qIiwiICIpKQp3cml0ZV9jc3YocmVkZGl0X0NvdmlkX2RhdGEsImRhdGFfaW4vcmVkZGl0X1NBLmNzdiIpCgpyZWRkaXRfQ292aWRfZGF0YSRkYXRlPSBkbXkocmVkZGl0X0NvdmlkX2RhdGEkZGF0ZSkKcmVkZGl0X0NvdmlkX2RhdGE8LSByZWRkaXRfQ292aWRfZGF0YSAlPiUgbXV0YXRlKCJYMSI9cm93X251bWJlcigpKQpgYGAKU2VudGltZW50IG9mIHJlZGRpdCBwb3N0cyB1c2luZyBTZW50aW1lbnRSCmBgYHtyfQpzZDwtIGdldF9zZW50ZW5jZXMocmVkZGl0X0NvdmlkX2RhdGEkdGl0bGUpCnJlZGRpdF9zZW50aW1lbnQ8LSBzZW50aW1lbnQoc2QpCgpyZWRkaXRfc2VudGltZW50PC0gbGVmdF9qb2luKHJlZGRpdF9Db3ZpZF9kYXRhLHJlZGRpdF9zZW50aW1lbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnk9YygiWDEiPSJlbGVtZW50X2lkIikpCgoKYGBgCgpNb2RlbGluZyBSZWRkaXQgc2VudGltZW50IG92ZXIgdGltZQpgYGB7cn0KZ2dwbG90KGRhdGE9cmVkZGl0X3NlbnRpbWVudCwgYWVzKHg9ZGF0ZSwgeT1yb2xsbWVhbihzZW50aW1lbnQsIDMwLCAgbmEucGFkPVRSVUUpKSkgKwogICAgICAgZ2VvbV9saW5lKGNvbG9yPSJwaW5rIiwgc2l6ZT0uNSkrCiAgZ2VvbV9zbW9vdGgoKSArCiAgdGhlbWVfbWluaW1hbCgpKwogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsMCksIGJyZWFrcyA9IGMoLTAuNCwtMC4yLDAsMC4yLDAuNCkpICsKICB5bGltKGMoLTAuNCwgMC40KSkrCiAgbGFicyh0aXRsZSA9ICJTZW50aW1lbnQgZnJvbSB0aGUgdGl0bGVzIG9mIFJlZGRpdCBwb3N0IGFib3V0IENvdmlkIGluIFNBIiwgeD0iRGF0ZSIsIAogICAgICAgeT0iU2VudGltZW50IikKYGBgCkFzIGNhbiBiZSBzZWVuIGZyb20gdGhlIGdyYXBoIHRoZSBzZW50aW1lbnQgb2YgdGhlIHBvc3RzIHN0YXJ0ZWQgb3V0IG1vcmUgbmVnYXRpdmUgYW5kIHRoYXQgd291bGQgY29ycmVsYXRlZCB0byBiZSBhcm91bmQgdG8gaGlnaGVyIGluZmVjdGlvbnMgcGVyIGRheS4gVGhlIHNlbnRpbWVudCBkb2VzIGhhdmUgYSBwb3NpdGl2ZSB0cmVuZCB0b3dhcmRzIHRoZSBlbmQgb2YgdGhlIHdhdmUgb2YgaW5mZWN0aW9ucy4gRXZlbiB0aG91Z2ggdGhlcmUgaXMgdmVyeSBzbGlnaHQgZmx1Y3R1YXRpb25zIHRoZSBwb3N0cyBzZWVtIG1vc3RseSBuZXV0cmFsLgoKLS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQpXaGF0IGZvbGxvd3MgaXMgdGhlIG1vZGVsaW5nIG9mIHRoZSBjb21tZW50IHNlY3Rpb25zIG9mIG1hbnkgb2YgdGhlIHBvc3RzIHdlIGZvdW5kLgpUaGUgUmVkZGl0IGhvbGUgb2YgY29tbWVudHMuIEFsbCB3aG8gZW50ZXIsIGJld2FyZSEKSGVyZSB3ZSBjcmVhdGUgYSBkYXRhZnJhbWUgZnJvbSBjb21tZW50cyBtYWRlIGJ5IHVzZXJzIG9uIHBvc3RzIHRoYXQgaGF2ZSB0aGUgdG9waWMgb2YgQ292aWQtMTkKCmBgYHtyIFNFVFVQfQpsaWJyYXJ5KHJ0d2VldCkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHl0ZXh0KQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkoc2NhbGVzKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGx1YnJpZGF0ZSkKbGlicmFyeSh2YWRlcikKbGlicmFyeSh0b3BpY21vZGVscykKbGlicmFyeShxdWFudGVkYSkKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkoem9vKQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeShmb3JjYXRzKQpsaWJyYXJ5KGlncmFwaCkKbGlicmFyeShnZ3JhcGgpCmxpYnJhcnkod2lkeXIpCmxpYnJhcnkocWRhcFJlZ2V4KQpsaWJyYXJ5KG1hZ2ljaykKYGBgCkhlcmUgd2UgZm91bmQgYSB3YXkgdG8gZ2V0IHRoZSBjb21tZW50IG9mIHRoZSBSZWRkaXQgcG9zdHMgdGhhdCB3ZXJlIG1vZGVsZWQgZWFybGllci4KYGBge3IgRmV0Y2hpbmcgUmVkZGl0IENvbW1lbnRzfQoKY29tbWVudHM8LSBnZXRfcmVkZGl0KHNlYXJjaF90ZXJtcyA9ICJDb3ZpZC0xOSIsIHN1YnJlZGRpdCA9ICJzb3V0aGFmcmljYSIsIHBhZ2VfdGhyZXNob2xkID0gNSwKICAgICAgICAgICAgICAgICAgICAgIHNvcnRfYnkgPSAibmV3IikKd3JpdGVfY3N2KGNvbW1lbnRzLCAiZGF0YV9pbi9yZWRkaXRfY29tbWVudHMuY3N2IikKYGBgCgoKV2UgZmlyc3QgY2xlYW4gdGhlIG9yaWdpbmFsIHRleHQgdG8gcmVtb3ZlIGxpbmtzLCBwdW5jdHVhdGlvbiwgZGlnaXRzLCBsaW5rcywgQCdzLgpUaGVuIHdlIHRva2VuaXplIHRoZSBjb21tZW50cyBhbmQgcmVtb3ZlIHN0b3Agd29yZHMgZnJvbSB0aWR5dGV4dCBhbmQgb3VyIG93biBzdG9wd29yZCBkaWN0aW9uYXJ5LiBXZSBhbHNvIHVzZSB0aGUgInR3aXR0ZXIiIHRva2VuIHRvIGhhbmRsZSBhbnkgbGVmdCBvdmVyIEAncyBhbmQgVVJMUy4KYGBge3IgQ2xlYW4gdXAsIGluY2x1ZGU9RkFMU0V9CiNjcmVhdGVkIGlmIG1vcmUgdHdlZXRzIGNvdWxkIGJlIGFjY2Vzc2VkIHRvIGJlIG1vcmUgdG9waWMgc3BlY2lmaWMKIyBjb3ZpZF9kaWN0aW9uYXJ5IDwtIGMoImhlcmQiLCAiaW1tdW5pdHkiLCAiaW5jdWJhdGlvbiIsICJqb2IiLCAibG9zcyIsICJLaXRzIiwgImxvY2tkb3duIiwgIm1hc2siLCAiTjk1IiwgIm91dGJyZWFrIiwgInBhbmRlbWljIiwgInF1YXJhbnRpbmUiLCAicmVjb3ZlcnkiLCAic2FuaXRpc2VyIiwgInRyYW5zbWlzc2lvbiIsICJVbmRlcmx5aW5nIiwgImNvbmRpdGlvbnMiLCAiVmVudGlsYXRvcnMiLCAiV0hPIiwgInhlbm9waG9iaWEiLCAieW91VHViZSIsICJ6b29ub3RpYyIsICJzdGF5LWF0LWhvbWUiLCAiY292aWQiLCAiY29yb25hdmlydXMiLCAiaHlyZG94eWNobG9yb3F1aW5lIiwgImFzeW1wdG9tYXRpYyIsICJmcm9udGxpbmUiLCAidmlydXMiLCAic2VsZi1pc29sYXRpb24iLCAiZGlzaW5mZWN0YW50IiwgInNoZWx0ZXItaW4tcGxhY2UiLCAibWFza3MiLCAiU0FSUy1Db1YtMiIsICJJQ1UiLCAiY29yb25hIiwgInJlb3BlbiIsICJkaXN0YW5jaW5nIiwgImNvdmVyaW5nIiwgImZ1cmxvdWdoIiwgInRyYWNlciIsICJlYXNpbmciLCAicmVtZGVzaXZpciIsICJtYWlsLWluIiwgImhvcm5ldCIsICJhbnRpYm9keSIsICJpbi1wZXJzb24iLCAiZGVmdW5kIiwgInJhY2lzbSIsICJsb290aW5nIiwgImxvb3QiLCAicmVvcGVuIiwgInR3by1tZXRyZSIsICJwYW5kZW1pYyIsICJsb290ZXIiLCAiZGlzdGFuY2luZyIsICJkZXhhbWV0aGFzb25lIiwgInJhY2lhbCIsICJ2YWNjaW5lIiwgImN1cmZldyIsImpvaG5zc29ucyIsICJhc3RyYXplbmVjYSIsICJob3NwaXRhbHMiLCAic29jaWFsLWRpc3RhbmNlIiwgInNvY2lhbC1kaXN0YW5jaW5nIiwgInBvbGljZSIsICJyZWd1bGF0aW9ucyIsICJzeW1wdG9tcyIsICJ0ZXN0aW5nIiwgInBvc2l0aXZlLXRlc3RzIiwgIm5lZ2F0aXZlLXRlc3RzIiAsICJjb25maXJtZWQtY2FzZXMiLCAicmVzdHJpY3Rpb25zIiwgImRlYXRocyIsICJpbmZlY3RlZCIsICJyZWNvdmVyaWVzIiwgImxldmVsIiwgImpvYnMiLCAidW5lbXBsb3llZCIsICJkb2N0b3JzIiwgImluZmVjdGlvbnMiLCAic2FuaXRpc2UiLCAic2FuaXRpc2VyIiwgInNhbml0aXNhdGlvbiIsICJjb250YWlubWVudCIpCgpyZWRkaXRfY29tbWVudHNfZGYgPC0gcmVhZF9jc3YoImRhdGFfaW4vcmVkZGl0X2NvbW1lbnRzLmNzdiIpCnJlZGRpdF9jb21tZW50c19kZiA8LQogIHJlZGRpdF9jb21tZW50c19kZlssIGNvbFN1bXMoaXMubmEocmVkZGl0X2NvbW1lbnRzX2RmKSkgPCBucm93KHJlZGRpdF9jb21tZW50c19kZildCgojSlVTVCB0aWR5CnJtX3R3aXR0ZXJfbl91cmwgPC0KICBybV8ocGF0dGVybiA9IHBhc3RleCgiQHJtX3R3aXR0ZXJfdXJsIiwgIkBybV91cmwiKSkKcmVkZGl0X2NvbW1lbnRzX2RmIDwtIHJlZGRpdF9jb21tZW50c19kZiAlPiUKICBtdXRhdGUoCiAgICBjb21tZW50ID0gcm1fdHdpdHRlcl9uX3VybChjb21tZW50KSwKICAgIGNvbW1lbnQgPSBnc3ViKCJAXFx3KyIsICIgIiwgY29tbWVudCksCiAgICBjb21tZW50ID0gZ3N1YigiW1s6cHVuY3Q6XV0iLCAiICIsIGNvbW1lbnQpLAogICAgY29tbWVudCA9IGdzdWIoIltbOmRpZ2l0Ol1dIiwgIiAiLCBjb21tZW50KSwKICAgIGNvbW1lbnQgPSBnc3ViKCJodHRwXFx3KyIsICIgIiwgY29tbWVudCksCiAgICBjb21tZW50ID0gZ3N1YigiWyB8XHRdezIsfSIsICIgIiwgY29tbWVudCksCiAgICBjb21tZW50ID0gZ3N1YigiXiAiLCAiICIsIGNvbW1lbnQpLAogICAgY29tbWVudCA9IGdzdWIoIiAkIiwgIiAiLCBjb21tZW50KSwKICAgIGNvbW1lbnQgPSBnc3ViKCJeQlVTSU5FU1MiLCAiICIsIGNvbW1lbnQpLAogICAgY29tbWVudCA9IGdzdWIoIl5Xb3JsZCIsICIgIiwgY29tbWVudCkKICApICU+JQogIG11dGF0ZSgKICAgIGNvbW1lbnQgPSBzdHJfcmVwbGFjZV9hbGwoY29tbWVudCwgIiA/KGZ8aHQpKHRwKShzPykoOi8vKSguKilbLnwvXSguKikiLCAiICIpLAogICAgY29tbWVudCA9IHN0cl9yZXBsYWNlX2FsbChjb21tZW50LCAiICIsICIgIiksCiAgICBjb21tZW50ID0gc3RyX3JlcGxhY2VfYWxsKGNvbW1lbnQsICJSVCBAW2EteixBLVpdKjogIiwgIiAiKSwKICAgIGNvbW1lbnQgPSBzdHJfcmVwbGFjZV9hbGwoY29tbWVudCwgIiNbYS16LEEtWl0qIiwgIiAiKSwKICAgIGNvbW1lbnQgPSBzdHJfcmVwbGFjZV9hbGwoY29tbWVudCwgIkBbYS16LEEtWl0qIiwgIiAiKQogICkKCiNtb3N0IHN0b3Agd29yZHMgYXJlIGZpbHRlcmVkIGJhc2VkIG9uIHRoZSBtZWRpYSBhZ2VuY2llcyB0YWcgYXQgdGhlIGJlZ2lubmluZyBvZiBlYWNoIFR3ZWV0LiBlZy4gV0FUQ0g6ICpoZWFkbGluZSBmb2xsb3dzKi4KYWdlbmN5X3N0b3Bfd29yZHMgPC0KICB0aWJibGUoCiAgICB3b3JkID0gYygKICAgICAgInNhYmNuZXdzIiwKICAgICAgImVuY2EiLAogICAgICAiZHN0diIsCiAgICAgICJzYWJja3puIiwKICAgICAgIm1hdmVyaWNrIiwKICAgICAgIm9waW5pb25pc3RhIiwKICAgICAgImRtIiwKICAgICAgInNjb3JwaW8iLAogICAgICAiZHN0djQwMyIsCiAgICAgICJpdHVzIiwKICAgICAgInJ0IiwKICAgICAgImFtcCIsCiAgICAgICJ0Z2lmb29kIiwKICAgICAgIm1hbWVsb2RpIiwKICAgICAgInN1bmRvd25zIiwKICAgICAgIm9mbWFnYXppbmVhdmFpbGFibGUiLAogICAgICAiY2FzYWJsYW5jYSIsCiAgICAgICJvcGVkIiwKICAgICAgIm5ld3NkZWNrIiwKICAgICAgImVkaXRvcmlhbCIsCiAgICAgICJuZXdmbGFzaCIsCiAgICAgICJzb3V0aGFmcmljYW5tb3JuaW5nIiwKICAgICAgIm5ld3NsaW5rIiwKICAgICAgImVuY2FzIiwKICAgICAgInNvdXRoYWZyaWNhdG9uaWdodCIsCiAgICAgICJ0aGVtaWRkYXl2aWV3IiwKICAgICAgInRoZWxlYWQiLAogICAgICAicHJvcGVydHltYXR0ZXJzIiwKICAgICAgImJhIiwKICAgICAgImthIiwKICAgICAgInlhIiwKICAgICAgImdhIiwKICAgICAgIndhIiwKICAgICAgImxlIiwKICAgICAgImt3YSIsCiAgICAgICJtb3JuaW5nbGl2ZXNhYmMiLAogICAgICAibW9uZGF5IiwKICAgICAgInByaXgiLAogICAgICAiYXplcmJhaWphbiIsCiAgICAgICJlbmNhc2lzIiwKICAgICAgImVuY2FidXNpbmVzcyIsCiAgICAgICJlbmNhc3NwZWFrcyIsCiAgICAgICJzb3V0aCIsCiAgICAgICJhZnJpY2EiLAogICAgICAicG0iLAogICAgICAic2EiLAogICAgICAicG0iLAogICAgICAiZW5jYXMiLAogICAgICAiaXNzIiwKICAgICAgImljeW1pIiwKICAgICAgInRpbWVzbGl2ZSIsCiAgICAgICJmdWxsdmlldyIsCiAgICAgICJuZXdzYnJlYWtzanVsIiwKICAgICAgIm5ld3NicmVha2p1bCIsCiAgICAgICJzYWJjIiwKICAgICAgIm5jYSIsCiAgICAgICJuY2FzIiwKICAgICAgIm9wIiwKICAgICAgImlnIiwKICAgICAgImVkIiwKICAgICAgInBsIiwKICAgICAgIm5ld3MyNCIsCiAgICAgICJuZXdzMjRzIiwKICAgICAgImRtMTY4IiwKICAgICAgInNpbmVzcyIsCiAgICAgICJ1c2luZXNzIiwKICAgICAgImV3c2RlY2siLAogICAgICAib3JsZCIsCiAgICAgICJzdW5kYXkiLAogICAgICAiZnJpZGF5IiwKICAgICAgInNhdHVyZGF5IiwKICAgICAgInRodXJzZGF5IiwKICAgICAgIndlZG5lc2RheSIsCiAgICAgICJtb25kYXkiLAogICAgICAidHVlc2RheSIsCiAgICAgICJwaWNzIiwKICAgICAgImxpdmUiCiAgICApCiAgKQoKI3RpZHkgZGYgYW5kIHVubmVzdAp0aWR5X3JlZGRpdF9kZiA8LSByZWRkaXRfY29tbWVudHNfZGYgJT4lCiAgI2ZpbHRlcihzdHJfZGV0ZWN0KHRleHQsIGZpeGVkKGNvdmlkX2RpY3Rpb25hcnksIGlnbm9yZV9jYXNlID0gVFJVRSkpKSAlPiUKICB1bm5lc3RfdG9rZW5zKHdvcmQsIGNvbW1lbnQsIHRva2VuID0gInR3ZWV0cyIpICU+JQogIGZpbHRlcigKICAgICF3b3JkICVpbiUgc3RvcF93b3JkcyR3b3JkLCF3b3JkICVpbiUgYWdlbmN5X3N0b3Bfd29yZHMkd29yZCwgCiAgICAhd29yZCAlaW4lIG5lZ2F0ZWRfd29yZHMkd29yZDIsIAogICAgIXdvcmQgJWluJSBzdHJfcmVtb3ZlX2FsbChzdG9wX3dvcmRzJHdvcmQsICInIiksCiAgICBzdHJfZGV0ZWN0KHdvcmQsICJbYS16XSIpCiAgKQoKYGBgCgpGcm9tIG91ciB0aWRpZWQgY29tbWVudCBkYXRhc2V0LCB3ZSBsb29rIGZvciB0aGUgdG9wIHdvcmRzIHRoYXQgYXBwZWFyLiBUaGlzIHdpbGwgZ2l2ZSB1cyBhIGdvb2QgaWRlYSBvZiB3aGF0IG1vc3QgcGVvcGxlIGNvbW1lbnQgYWJvdXQuIFdlIGZpbmQgdGhhdCBtb3N0IHBlb3BsZSB0YWxrIGFib3V0IG90aGVyIHBlb3BsZSB1c3VhbGx5IGluIGNvbmp1bmN0aW9uIHdpdGggb3RoZXIgd29yZHMgbGlrZSB2YWNjaW5lcyBvciBjb3ZpZC4KYGBge3IgdG9wIHdvcmRzfQojdG9wIHdvcmRzCnRvcF93b3JkcyA8LSB0aWR5X3JlZGRpdF9kZiAlPiUKICBhbnRpX2pvaW4oc3RvcF93b3JkcykgJT4lCiAgY291bnQod29yZCkgJT4lCiAgYXJyYW5nZShkZXNjKG4pKQp0b3Bfd29yZHMgJT4lCiAgc2xpY2UoMToyMCkgJT4lCiAgZ2dwbG90KGFlcyhyZW9yZGVyKHdvcmQsLW4pLCBuLCBmaWxsID0gd29yZCkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dCgKICAgICAgYW5nbGUgPSA2MCwKICAgICAgaGp1c3QgPSAxLAogICAgICBzaXplID0gMTMKICAgICksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMTgpCiAgKSArCiAgeWxhYigiRnJlcXVlbmN5IikgKwogIHhsYWIgKCIiKSArCiAgZ2d0aXRsZSgiTW9zdCBmcmVxdWVudCB3b3JkcyB1c2VkIGluIHJlZGRpdCBjb21tZW50cyIpICsKICBndWlkZXMoZmlsbCA9IEZBTFNFKQpgYGAKCkFmdGVyIGNoYW5naW5nLCBhZGRpbmcsIGFuZCByZW1vdmluZyB0ZXJtcyBmcm9tIHRoZSBmaWx0ZXJzLCB3ZSBjYW4gY29uY2x1ZGUgdGhhdCB0aGUgdGYtaWRmIGFuYXlsc2lzIGlzIG5vdCB1c2VmdWwgZm9yIHRoZXNlIGNvbW1lbnRzLiBUaGUgc2ltcGxlIGFtb3VudCBvZiBjb21tZW50IGRhdGEgcGVyIHBvc3QgYW5kIHRoZSBmYWN0IHRoYXQgdGhlIHRpbWUgZnJhbWVzIGFyZSBzcG9yYWRpYyBtYWtlIHRoYXQgeW91IGFyZSB1bmFibGUgdG8gLiBXaGVuIHRmLWlkZiBydW5zLCBpdCBpbmNyZWFzZXMgdGhlaXIgdGVybSB3ZWlnaHRzIGFzIHRoZXkgYXJlICJ1bmlxdWUiIGJlY2F1c2UgdGhleSBhcmUgbm90IGZvdW5kIGFtb25nIG90aGVyIG1lZGlhIGFnZW5jaWVzLiBUaGVzZSB3b3JkcyBhcmUgdXN1YWxseSBub3QgdGVsbGluZy4gV2hhdCBpdCBjYW4gdGVsbCB1cyAtIHdoaWNoIHNlZ21lbnRzIHRoZXNlIG1lZGlhIGFnZW5jaWVzIHBvc3QgYWJvdXQgdGhlIG1vc3QuCmBgYHtyIHRmLWlkZiBmcmVxdWVuY3kgcGVyIHBvc3R9CiN0Zi1pZGYKdGlkeV9yZWRkaXRfdGZfaWRmIDwtIHRpZHlfcmVkZGl0X2RmICU+JQogIHNlbGVjdChhdXRob3IsIHdvcmQpICU+JQogIGdyb3VwX2J5KGF1dGhvcikgJT4lCiAgY291bnQod29yZCwgYXV0aG9yKSAlPiUKICBiaW5kX3RmX2lkZih3b3JkLCBhdXRob3IsIG4pCgojY2FsY3VsYXRlIGEgZnJlcXVlbmN5IGZvciBlYWNoIGFnZW5jeSBhbmQgd29yZApmcmVxdWVuY3kgPC0gdGlkeV9yZWRkaXRfdGZfaWRmICU+JQogIGdyb3VwX2J5KGF1dGhvcikgJT4lCiAgY291bnQod29yZCwgc29ydCA9IFRSVUUpICU+JQogIGxlZnRfam9pbih0aWR5X3JlZGRpdF9kZiAlPiUKICAgICAgICAgICAgICBncm91cF9ieShhdXRob3IpICU+JQogICAgICAgICAgICAgIHN1bW1hcmlzZSh0b3RhbCA9IG4oKSkpICU+JQogIG11dGF0ZShmcmVxID0gbiAvIHRvdGFsKQoKdGlkeV9yZWRkaXRfdGZfaWRmICU+JQogIGdyb3VwX2J5KGF1dGhvcikgJT4lCiAgc2xpY2VfbWF4KHRmX2lkZiwgbiA9IDE1KSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZ2dwbG90KGFlcyh0Zl9pZGYsIGZjdF9yZW9yZGVyKHdvcmQsIHRmX2lkZiksIGZpbGwgPSBhdXRob3IpKSArCiAgZ2VvbV9jb2woc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGZhY2V0X3dyYXAofiBhdXRob3IsIG5jb2wgPSAyLCBzY2FsZXMgPSAiZnJlZSIpICsKICBsYWJzKHggPSAidGYtaWRmIiwgeSA9IE5VTEwpCmBgYAoKQnkgbW9kZWxpbmcgYmlncmFtcyBhbmQgdHJpZ3JhbXMgZm9yIG91ciBkYXRhc2V0IGdpdmVzIHVzIGEgYmV0dGVyIHVuZGVyc3RhbmRpbmcgb2Ygd2hhdCB0b3BpYyBpcyBiZWluZyBkaXNjdXNzZWQgd2l0aCBlYWNoIHdvcmQuIFdlIGNhbiB0aGVuIGFsc28gc2VlIHdoaWNoIHNlbnRpbWVudHMgYXJlIGluY29ycmVjdGx5IGxhYmVsZWQuICJub3QgZ29vZCIgZ2l2ZXMgYmV0dGVyIGNvbnRleHQgb2YgYSBuZWdhdGl2ZSBzZW50aW1lbnQsIHJhdGhlciB0aGFuIGl0IGJlaW5nIGluY29ycmVjdGx5IGlkZW50aWZpZWQgYXMgcG9zaXRpdmUgZ29vZC4gQWx0aG91Z2ggdGhpcyB3b3JrcyByZWFsbHkgd2VsbCBmb3IgVHdpdHRlciwgaXQgZG9lcyBub3Qgc2VlbXMgdG8gY2FycnkgdGhyb3VnaCB0aGF0IHdlbGwgdG8gdGhlIHBvaW50IG9mIGludGVycHJldGF0aW9uIGZvciBSZWRkaXQgZGF0YS4KYGBge3IgYmlncmFtc30KI2JpZ3JhbXMKdGlkeV9iaWdyYW1fZGYgPC0gcmVkZGl0X2NvbW1lbnRzX2RmICU+JQogICNmaWx0ZXIoc3RyX2RldGVjdCh0ZXh0LCBmaXhlZChjb3ZpZF9kaWN0aW9uYXJ5LCBpZ25vcmVfY2FzZSA9IFRSVUUpKSkgJT4lCiAgZmlsdGVyKCFzdHJfZGV0ZWN0KGNvbW1lbnQsICJeUlQiKSkgJT4lCiAgbXV0YXRlKGNvbW1lbnQgPSBnc3ViKCIgPyhmfGh0KXRwKHM/KTovLyguKilbLl1bYS16XSsiLCAiICIsIGNvbW1lbnQpKSAlPiUKICB1bm5lc3RfdG9rZW5zKGJpZ3JhbSwgY29tbWVudCwgdG9rZW4gPSAibmdyYW1zIiwgbiA9IDIpICU+JQogIHNlcGFyYXRlKGJpZ3JhbSwgYygid29yZDEiLCAid29yZDIiKSwgc2VwID0gIiAiKQoKYmlncmFtc19maWx0ZXJlZCA8LSB0aWR5X2JpZ3JhbV9kZiAlPiUKICBmaWx0ZXIoIXdvcmQxICVpbiUgc3RvcF93b3JkcyR3b3JkKSAlPiUKICBmaWx0ZXIoIXdvcmQyICVpbiUgc3RvcF93b3JkcyR3b3JkKQoKIyBuZXcgYmlncmFtIGNvdW50czoKYmlncmFtX2NvdW50cyA8LSBiaWdyYW1zX2ZpbHRlcmVkICU+JQogIGNvdW50KHdvcmQxLCB3b3JkMiwgc29ydCA9IFRSVUUpCgpiaWdyYW1zX3VuaXRlZCA8LSBiaWdyYW1zX2ZpbHRlcmVkICU+JQogIHVuaXRlKGJpZ3JhbSwgd29yZDEsIHdvcmQyLCBzZXAgPSAiICIpCgojdGYtaWRmIGJpZ3JhbXMKYmlncmFtX3RmX2lkZiA8LSBiaWdyYW1zX3VuaXRlZCAlPiUKICBjb3VudChhdXRob3IsIGJpZ3JhbSkgJT4lCiAgYmluZF90Zl9pZGYoYmlncmFtLCBhdXRob3IsIG4pICU+JQogIGFycmFuZ2UoZGVzYyh0Zl9pZGYpKQoKYmlncmFtX3RmX2lkZiAlPiUKICBncm91cF9ieShhdXRob3IpICU+JQogIHNsaWNlX21heCh0Zl9pZGYsIG4gPSAxNSkgJT4lCiAgdW5ncm91cCgpICU+JQogIGdncGxvdChhZXModGZfaWRmLCBmY3RfcmVvcmRlcihiaWdyYW0sIHRmX2lkZiksIGZpbGwgPSBhdXRob3IpKSArCiAgZ2VvbV9jb2woc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGZhY2V0X3dyYXAoIH4gYXV0aG9yLCBuY29sID0gMiwgc2NhbGVzID0gImZyZWUiKSArCiAgbGFicyh4ID0gInRmLWlkZiIsIHkgPSBOVUxMKQoKI3dlaWdodHMgYW5kIGdyYXBocwpiaWdyYW1fZ3JhcGggPC0gYmlncmFtX2NvdW50cyAlPiUKICBmaWx0ZXIobiA+IDEwMCkgJT4lCiAgZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKCkKCnNldC5zZWVkKDEyMzQpCmEgPC0gZ3JpZDo6YXJyb3codHlwZSA9ICJjbG9zZWQiLCBsZW5ndGggPSB1bml0KC4xNSwgImluY2hlcyIpKQpnZ3JhcGgoYmlncmFtX2dyYXBoLCBsYXlvdXQgPSAiZnIiKSArCiAgZ2VvbV9lZGdlX2xpbmsoCiAgICBhZXMoZWRnZV9hbHBoYSA9IG4pLAogICAgc2hvdy5sZWdlbmQgPSBGQUxTRSwKICAgIGFycm93ID0gYSwKICAgIGVuZF9jYXAgPSBjaXJjbGUoLjA3LCAnaW5jaGVzJykKICApICsKICBnZW9tX25vZGVfcG9pbnQoY29sb3IgPSAibGlnaHRibHVlIiwgc2l6ZSA9IDUpICsKICBnZW9tX25vZGVfdGV4dChhZXMobGFiZWwgPSBuYW1lKSwKICAgICAgICAgICAgICAgICB2anVzdCA9IDEsCiAgICAgICAgICAgICAgICAgaGp1c3QgPSAxLAogICAgICAgICAgICAgICAgIHJlcGVsID0gVFJVRSkgKwogIHRoZW1lX3ZvaWQoKQpgYGAKCldlIGdpdmUgbW9yZSB3ZWlnaHQgdG8gd29yZHMgdGhhdCBhcHBlYXIgbW9yZSBvZnRlbiB3aXRoIHRoZSBpbmNvcnJlY3Qgc2VudGltZW50LiBXZSBjYW4gbm93IHJldmVyc2UgdGhlIHNlbnRpbWVudCBvZiB0aGVzZSB3b3JkcyBvbmNlIFZBREVSIGhhcyBiZWVuIHJ1biBvbiB0aGUgZGF0YXNldC4KYGBge3IgbmVnYXRpb24gd29yZHN9CiN2YWRlciBsZXhpY29uIGltcG9ydGVkIGZyb20gVkFERVIgR2l0SHViCnZhZGVyX2xleGljb24gPC0gcmVhZF9jc3YyKCJkYXRhX2luL3ZhZGVyX2xleGljb24uY3N2IikgJT4lCiAgcmVuYW1lKCJ3b3JkIiA9IFRPS0VOLCAidmFsdWUiID0gYE1FQU4tU0VOVElNRU5ULVJBVElOR2ApCgojY29tbW9uIG5lZ2F0aW9uIHdvcmRzCm5lZ2F0aW9uX3dvcmRzIDwtCiAgYygKICAgICJub3QiLAogICAgIm5vIiwKICAgICJuZXZlciIsCiAgICAid2l0aG91dCIsCiAgICAibm8iLAogICAgIm5vdCIsCiAgICAibm9uZSIsCiAgICAibm8gb25lIiwKICAgICJub2JvZHkiLAogICAgIm5vdGhpbmciLAogICAgIm5laXRoZXIiLAogICAgIm5vd2hlcmUiLAogICAgIm5ldmVyIiwKICAgICJkb2VzbuKAmXQiLAogICAgImlzbuKAmXQiLAogICAgIndhc27igJl0IiwKICAgICJzaG91bGRu4oCZdCIsCiAgICAid291bGRu4oCZdCIsCiAgICAiY291bGRu4oCZdCIsCiAgICAid29u4oCZdCIsCiAgICAiY2Fu4oCZdCIsCiAgICAiZG9u4oCZdCIKICApCm5lZ2F0ZWRfd29yZHMgPC0gdGlkeV9iaWdyYW1fZGYgJT4lCiAgZmlsdGVyKHdvcmQxICVpbiUgZml4ZWQobmVnYXRpb25fd29yZHMsIGlnbm9yZV9jYXNlID0gVFJVRSkpICU+JQogIGlubmVyX2pvaW4odmFkZXJfbGV4aWNvbiwgYnkgPSBjKHdvcmQyID0gIndvcmQiKSkgJT4lCiAgbXV0YXRlKHZhbHVlID0gYXMuZG91YmxlKHZhbHVlKSkgJT4lCiAgY291bnQod29yZDEsIHdvcmQyLCB2YWx1ZSwgc29ydCA9IFRSVUUpICU+JQogIG11dGF0ZShjb250cmlidXRpb24gPSBuICogdmFsdWUpICU+JQogIGFycmFuZ2UoZGVzYyhhYnMoY29udHJpYnV0aW9uKSkpICU+JQogIG11dGF0ZSh3b3JkMiA9IHJlb3JkZXIod29yZDIsIGNvbnRyaWJ1dGlvbikpCm5lZ2F0ZWRfd29yZHMgJT4lCiAgaGVhZCg0MCkgJT4lCiAgZ2dwbG90KGFlcyhuICogdmFsdWUsIHdvcmQyLCBmaWxsID0gbiAqIHZhbHVlID4gMCkpICsKICBnZW9tX2NvbChzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgZmFjZXRfd3JhcCggfiB3b3JkMSwgc2NhbGVzID0gImZyZWVfeSIpICsKICBsYWJzKHggPSAiU2VudGltZW50IHZhbHVlICogIyBudW1iZXIgb2Ygb2NjdXJyZW5jZXMiLAogICAgICAgeSA9ICJXb3JkcyBwcmVjZWRlZCBieSBuZWdhdGlvbiB0ZXJtcyIpCgpgYGAKCgpUaGUgZ3JhcGggYmVsb3cgc2hvd3Mgd2hpY2ggd29yZHMgYXJlIG1vc3QgbGlrZWx5IHRvIGNvLW9jY3VyLiBXZSB1c2UgdGhpcyB0byB1bmRlcnN0YW5kIHRoZSBjb250ZXh0IG9mIHdvcmRzIGluIG91ciB0b3BpYyBtb2RlbGxpbmcuCmBgYHtyIENvdW50aW5nIGFuZCBjb3JyZWxhdGluZyBhbW9uZyBzZWN0aW9ucywgd2FybmluZz1GQUxTRX0KcmVkZGl0X2NvbW1lbnRzX3NlY3Rpb25fd29yZHMgPC0gdGlkeV9yZWRkaXRfZGYgJT4lCiAgbXV0YXRlKHNlY3Rpb24gPSByb3dfbnVtYmVyKCkgJS8lIDEwKSAlPiUKICBmaWx0ZXIoc2VjdGlvbiA+IDApCgojIGNvdW50IHdvcmRzIGNvLW9jY3VyaW5nIHdpdGhpbiBzZWN0aW9ucwp3b3JkX3BhaXJzIDwtIHJlZGRpdF9jb21tZW50c19zZWN0aW9uX3dvcmRzICU+JQogIHBhaXJ3aXNlX2NvdW50KHdvcmQsIHNlY3Rpb24sIHNvcnQgPSBUUlVFKQoKIyB3ZSBuZWVkIHRvIGZpbHRlciBmb3IgYXQgbGVhc3QgcmVsYXRpdmVseSBjb21tb24gd29yZHMgZmlyc3QKd29yZF9jb3JzIDwtIHJlZGRpdF9jb21tZW50c19zZWN0aW9uX3dvcmRzICU+JQogIGdyb3VwX2J5KHdvcmQpICU+JQogIGZpbHRlcihuKCkgPj0gMjApICU+JQogIHBhaXJ3aXNlX2Nvcih3b3JkLCBzZWN0aW9uLCBzb3J0ID0gVFJVRSklPiUKICBmaWx0ZXIoY29ycmVsYXRpb24+PS4wNSkKICAgCiAgCgojIENvcnJlbGF0aW9uIG9mIG5leHQgd29yZAojIHdvcmRfY29ycyAlPiUKIyAgIGZpbHRlcihpdGVtMSA9PSAidmFjY2luZSIpCgp3b3JkX2NvcnMgJT4lCiAgZmlsdGVyKGl0ZW0xICVpbiUgYygiY292aWQiLCAidmFjY2luZSIsICJsb2NrZG93biIsICJ6dW1hIiwgImdhdXRlbmciLCAicmFtYXBob3NhIikpICU+JQogIGdyb3VwX2J5KGl0ZW0xKSAlPiUKICBzbGljZV9tYXgoY29ycmVsYXRpb24sIG4gPSA2KSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKGl0ZW0yID0gcmVvcmRlcihpdGVtMiwgY29ycmVsYXRpb24pKSAlPiUKICBnZ3Bsb3QoYWVzKGl0ZW0yLCBjb3JyZWxhdGlvbikpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGZhY2V0X3dyYXAoIH4gaXRlbTEsIHNjYWxlcyA9ICJmcmVlIikgKwogIGNvb3JkX2ZsaXAoKSAKICAKCnNldC5zZWVkKDEyMzQpCndvcmRfY29ycyAlPiUKICBncmFwaF9mcm9tX2RhdGFfZnJhbWUoKSAlPiUKICBnZ3JhcGgobGF5b3V0ID0gImZyIikgKwogIGdlb21fZWRnZV9saW5rKGFlcyhlZGdlX2FscGhhID0gY29ycmVsYXRpb24pLAogICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgZWRnZV93aWR0aCA9IDMpICsKICBnZW9tX25vZGVfcG9pbnQoY29sb3IgPSAibGlnaHRibHVlIiwgc2l6ZSA9IDUpICsKICBnZW9tX25vZGVfdGV4dChhZXMobGFiZWwgPSBuYW1lKSwgcmVwZWwgPSBUUlVFKSArCiAgdGhlbWVfdm9pZCgpCmBgYAoKV2hhdCB3ZSBub3RpY2VkIGhlcmUgaXMgdGhhdCBhbG90IG9mIHRoZSBkYXRhIGlzIGRpZmZpY3VsdCB0byBtb2RlbCBkdWUgdG8gdGhlIHNpemUgYW5kIHRoZSBhbW91bnQgb2YgZGlmZmVyZW50IHBvc3RzLiBXaGF0IHdlIGNhbiBob3dldmVyIHNlZSBpcyB0aGF0IG1vcmUgcmVjZW50IHR3ZWV0cyBzZWVtIHRvIGhhdmUgYSBtb3JlIG5lZ2F0aXZlIGNvbXBvdW5kIHNlbnRpbWVudCB2YWx1ZSB0aGFuIHR3ZWV0cyBmcm9tIGVhcmxpZXIgdGhpcyB5ZWFyLgpgYGB7ciBWQURFUn0KI3ZhZGVyX2RmIDwtIHZhZGVyX2RmKHJlZGRpdF9jb21tZW50c19kZiRjb21tZW50KQojd3JpdGVfYXNfY3N2KHZhZGVyX2RmLCAiZGF0YV9pbi92YWRlcl9yZWRkaXRfY29tbWVudHMiKQoKIAoKdmFkZXJfZGYgPC0gcmVhZF9jc3YoImRhdGFfaW4vdmFkZXJfcmVkZGl0X2NvbW1lbnRzLmNzdiIpCnZhZGVyX2RmIDwtIHZhZGVyX2RmICU+JSBtdXRhdGUoIlgxIiA9IHJvd19udW1iZXIoKSkKcmVkZGl0X2NvbW1lbnRzX2RmIDwtIHJlZGRpdF9jb21tZW50c19kZiAlPiUgbXV0YXRlKCJYMSIgPSByb3dfbnVtYmVyKCkpCnJlZGRpdF9jb21tZW50c192YWRlciA8LSByZWRkaXRfY29tbWVudHNfZGYgJT4lIGxlZnRfam9pbih2YWRlcl9kZiwgYnkgPSAiWDEiKQoKI0dlbmVyYWwgc2VudGltZW50IG92ZXIgdGltZS4gTWVkaWEgYWdlbmNpZXMgc2VlbSB0byBoYXZlIGFuIGV2ZW4gbnVtYmVyIG9mIHBvc2l0aXZlIGFuZCBuZWdhdGl2ZSB0d2VldHMgcGVyIGRheS4KZ2dwbG90KAogIHJlZGRpdF9jb21tZW50c192YWRlciAlPiUKICAgIG11dGF0ZShwb3N0X2RhdGUgPSBhcy5EYXRlKHBvc3RfZGF0ZSkpICU+JQogICAgZ3JvdXBfYnkocG9zdF9kYXRlLCBhdXRob3IpICU+JQogICAgbXV0YXRlKGNvbXBvdW5kID0gcmVwbGFjZShjb21wb3VuZCwgaXMubmEoY29tcG91bmQpLCAwKSkgJT4lCiAgICBzdW1tYXJpc2Uoc3VtX2NvbXBvdW5kID0gc3VtKGFzLmRvdWJsZShjb21wb3VuZCkpKSwKICBhZXMocG9zdF9kYXRlLCBzdW1fY29tcG91bmQsIGZpbGwgPSBhdXRob3IpCikgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgbmEucm0gPSBUUlVFLCBzZSA9IEZBTFNFKSArCiAgZmFjZXRfd3JhcCggfiBhdXRob3IsIHNjYWxlcyA9ICJmcmVlX3giLCBuY29sID0gMikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMyBkYXkiLCBkYXRlX2xhYmVscyA9ICIlbS0lZCIpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KAogICAgICBhbmdsZSA9IDkwLAogICAgICB2anVzdCA9IDAuNSwKICAgICAgaGp1c3QgPSAxCiAgICApLAogICAgcGFuZWwuZ3JpZC5taW5vci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpLAogICkKCgpnZ3Bsb3QoCiAgcmVkZGl0X2NvbW1lbnRzX3ZhZGVyICU+JQogICAgbXV0YXRlKHBvc3RfZGF0ZSA9IGFzLkRhdGUocG9zdF9kYXRlKSkgJT4lCiAgICBncm91cF9ieShwb3N0X2RhdGUpICU+JQogICAgZmlsdGVyKGF1dGhvciA9PSAiYW5nZWxfeWVsbG93X2JyaWNrIikgJT4lCiAgICBzdW1tYXJpc2UoY29tcG91bmQpLAogIGFlcyhwb3N0X2RhdGUsIGNvbXBvdW5kKQopICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIG5hLnJtID0gVFJVRSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpCgojTmV3cyBzZW50aW1lbnQKcmVkZGl0X2NvbW1lbnRzX3ZhZGVyICU+JQogIG11dGF0ZShwb3N0X2RhdGUgPSBhcy5EYXRlKHBvc3RfZGF0ZSkpICU+JQogIGdyb3VwX2J5KHBvc3RfZGF0ZSwgYXV0aG9yKSAlPiUKICBzdW1tYXJpc2UoY29tcG91bmQpICU+JQogIGFycmFuZ2UoZGVzYyhjb21wb3VuZCkpCgpnZ3Bsb3QocmVkZGl0X2NvbW1lbnRzX3ZhZGVyICU+JSBhcnJhbmdlKGNvbXBvdW5kKSAlPiUgbXV0YXRlKFgxID0gZmFjdG9yKFgxLCBsZXZlbHMgPSBYMSkpLAogICAgICAgYWVzKHggPSBYMSkpICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSAgYWVzKHkgPSBjb21wb3VuZCkpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsIDApKQoKcmVkZGl0X2NvbW1lbnRzX3ZhZGVyJT4lCiAgbXV0YXRlKHBvc3RfZGF0ZSA9IGFzLkRhdGUocG9zdF9kYXRlLCBmb3JtYXQgPSAiJWQtJW0tJXkiKSkgJT4lCiAgZ3JvdXBfYnkocG9zdF9kYXRlLCBhdXRob3IpICU+JQogIG11dGF0ZShjb21wb3VuZCA9IHJlcGxhY2UoY29tcG91bmQsIGlzLm5hKGNvbXBvdW5kKSwgMCkpICU+JQogIHN1bW1hcmlzZShzdW1fY29tcG91bmQgPSBzdW0oYXMuZG91YmxlKGNvbXBvdW5kKSkpCmBgYAoKVGhlIHBsb3QgYmVsb3cgbWFwcyB0aGUgYXZlcmFnZSB0b3RhbCBjb21tZW50cyBvbiBhIHBvc3QgcGVyIGRheS4KYGBge3IgSW50ZXJhY3Rpb25zLCBlY2hvPUZBTFNFfQojIG1lZGlhX3ZhZGVyX2RmICU+JSBzZWxlY3QoZmF2b3JpdGVfY291bnQsIHJldHdlZXRfY291bnQpICU+JSBtdXRhdGUoZmF2b3JpdGVfY291bnQgKyByZXR3ZWV0X2NvdW50KQoKcmVkZGl0X2NvbW1lbnRzX3ZhZGVyIDwtIHJlZGRpdF9jb21tZW50c192YWRlciAlPiUKICBtdXRhdGUocG9zdF9kYXRlID0gYXMuRGF0ZShwb3N0X2RhdGUsIGZvcm1hdCA9ICIlZC0lbS0leSIpKSAlPiUKICBncm91cF9ieShwb3N0X2RhdGUpICU+JQogIG11dGF0ZSgKICAgIHJldHdlZXRfZGFpbHkgPSBtZWFuKG51bV9jb21tZW50cyksCiAgICBmYXZvcml0ZV9kYWlseSA9IG1lYW4oY29tbWVudF9zY29yZSksCiAgICB0b3RhbCA9IG1lYW4obnVtX2NvbW1lbnRzICsgY29tbWVudF9zY29yZSkKICApCiMgbWVhbiBmb3IgdGhlIGRheQppbnRlcmFjdGlvbnNfcGxvdCA8LSBnZ3Bsb3RseSgKICBnZ3Bsb3QoZGF0YSA9IHJlZGRpdF9jb21tZW50c192YWRlciwgYWVzKHBvc3RfZGF0ZSkpICsKICAgIGdlb21fcmliYm9uKGFlcygKICAgICAgeW1pbiA9IDAsIHltYXggPSB0b3RhbCwgZmlsbCA9ICJUb3RhbCIKICAgICkpICsKICAgIGdlb21fcmliYm9uKGFlcygKICAgICAgeW1pbiA9IDAsIHltYXggPSBmYXZvcml0ZV9kYWlseSwgZmlsbCA9ICJDb21tZW50X3Njb3JlIgogICAgKSkgKwogICAgZ2VvbV9yaWJib24oYWVzKAogICAgICB5bWluID0gMCwgeW1heCA9IHJldHdlZXRfZGFpbHksIGZpbGwgPSAiTnVtYmVyIG9mQ29tbWVudHMiCiAgICApKSArCiAgICB0aGVtZSgKICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIAogICAgICBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMCwgMCksCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMCwgMCksCiAgICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIAogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KAogICAgICAgIHNpemUgPSAxNCwKICAgICAgICBmYWNlID0gImJvbGQiLAogICAgICAgIG1hcmdpbiA9IG1hcmdpbigwLCAwLCAxMCwgMCksCiAgICAgICAgaGp1c3QgPSAwCiAgICAgICksCiAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBoanVzdCA9IDApLAogICAgKQogICwKICB0b29sdGlwID0gYygidG90YWwiLCAiZmF2b3JpdGVfZGFpbHkiLCAicmV0d2VldF9kYWlseSIsICJwb3N0X2RhdGUiKQopCgojIHBlYWsgdHdlZXRzIGJ5IGRheQojIG1lZGlhX3ZhZGVyX2RmICU+JQojICAgZmlsdGVyKGNyZWF0ZWRfYXQgPT0gIjIwMjEtMDUtMDEiICkgJT4lCiMgICBzbGljZV9tYXgoZmF2b3JpdGVfY291bnQgKyByZXR3ZWV0X2NvdW50KQojIG1lZGlhX3ZhZGVyX2RmICU+JQojICAgZmlsdGVyKGNyZWF0ZWRfYXQgPT0gIjIwMjEtMDUtMjMiICkgJT4lCiMgICBzbGljZV9tYXgoZmF2b3JpdGVfY291bnQgKyByZXR3ZWV0X2NvdW50KQojIG1lZGlhX3ZhZGVyX2RmICU+JQojICAgZmlsdGVyKGNyZWF0ZWRfYXQgPT0gIjIwMjEtMDUtMjkiICkgJT4lCiMgICBzbGljZV9tYXgoZmF2b3JpdGVfY291bnQgKyByZXR3ZWV0X2NvdW50KQojIG1lZGlhX3ZhZGVyX2RmICU+JQojICAgZmlsdGVyKGNyZWF0ZWRfYXQgPT0gIjIwMjEtMDYtMDIiICkgJT4lCiMgICBzbGljZV9tYXgoZmF2b3JpdGVfY291bnQgKyByZXR3ZWV0X2NvdW50KQojIG1lZGlhX3ZhZGVyX2RmICU+JQojICAgZmlsdGVyKGNyZWF0ZWRfYXQgPT0gIjIwMjEtMDYtMDYiICkgJT4lCiMgICBzbGljZV9tYXgoZmF2b3JpdGVfY291bnQgKyByZXR3ZWV0X2NvdW50KQojIG1lZGlhX3ZhZGVyX2RmICU+JQojICAgZmlsdGVyKGNyZWF0ZWRfYXQgPT0gIjIwMjEtMDYtMjYiICkgJT4lCiMgICBzbGljZV9tYXgoZmF2b3JpdGVfY291bnQgKyByZXR3ZWV0X2NvdW50KQojIG1lZGlhX3ZhZGVyX2RmICU+JQojICAgZmlsdGVyKGNyZWF0ZWRfYXQgPT0gIjIwMjEtMDctMDMiICkgJT4lCiMgICBzbGljZV9tYXgoZmF2b3JpdGVfY291bnQgKyByZXR3ZWV0X2NvdW50KQoKIyBtZWRpYV92YWRlcl9kZiAlPiUKIyAgIGdyb3VwX2J5KHNjcmVlbl9uYW1lKSAlPiUKIyAgIHNsaWNlX21heChmYXZvcml0ZV9jb3VudCArIHJldHdlZXRfY291bnQpCgojIHBlYWsgdHdlZXRzIGJ5IHVzZXIKIyBAZU5DQTogQ2FsbCBmb3IgbWluaXN0ZXJzIG92ZXIgNjAgdG8gcmVzaWduLgojIEBkYWlseW1hdmVyaWNrOiBGbG95ZCBTaGl2YW1ideKAmXMgYnJvdGhlciBxdWlldGx5IHBheXMgYmFjayBSbSBhZG1pdHMgaGUgcmVjZWl2ZWQgdGhlIFZCUyBtb25leSBncmF0dWl0b3VzbHkuCiMgQFRpbWVzTElWRToJRG8geW91IGFwcHJvdmUgb2YgRHVkdXphbmUgcnVubmluZyBmb3IgcHJlc2lkZW50PwojIEBOZXdzMjQ6IENvY2EtQ29sYSBsb3N0ICQ0IGJpbGxpb24gaW4gbWFya2V0IHZhbHVlIGFmdGVyIENyaXN0aWFubyBSb25hbGRvIHN1Z2dlc3RlZCBwZW9wbGUgZHJpbmsgd2F0ZXIgaW5zdGVhZC4KIyBAU0FCQ05ld3M6IEJSRUFLSU5HIE5FV1M6IEtpbmcgb2YgRXN3YXRpbmkgaGFzIGZsZWQgYW1pZCBwdWJsaWMgdmlvbGVuY2UgaW4gdGhlIGNvdW50cnkuCgojaW1hZ2VfcmVhZCgiaW1hZ2VzL2ludGVyYWN0aW9uc19wbG90LnBuZyIpCmludGVyYWN0aW9uc19wbG90CmBgYAoKT3VyIG1haW4gdG9waWMgaW5mbHVlbmNlIGlzIENPVklELTE5IGFzIHRoaXMgaXMgd2hhdCBjdXJyZW50bHkgYWZmZWN0cyB0aGUgY291bnRyeSB0aGUgbW9zdC4gV2UgYmFzZWQgb3VyIGRhdGEgY29sbGVjdGlvbiBhcm91bmQgdGhlIHdvcmQgQ09WSUQtMTkgYW5kIGV4cGVjdCB0byBzZWUgYSBsb3Qgb2YgaW50ZXIgcmVsYXRlZCB0ZXJtcyBhYm91dCBpdCBzcHJlYWQgdGhyb3VnaG91dCB0aGUgZGlmZmVyZW50IHRvcGljcy4gQXMgeW91IGNhbiBzZWUsIGR1ZSB0byB0aGUgZmFjdCB0aGF0IHRoZSBwb3N0cyB3ZXJlIGFsbCBhYm91dCBDb3ZpZCwgdGhlIGNvbW1lbnRzIGFsbCBpbmhlcml0ZWQgdGhlIG92ZXJhcmNoaW5nIHRvcGljLgpgYGB7ciBUb3BpYyBNb2RlbGxpbmd9CnRpZHlfbWF0cml4IDwtCiAgdGlkeV9yZWRkaXRfZGYgJT4lIHNhbXBsZSh0aWR5X3JlZGRpdF9kZiwgc2l6ZT0wLjEpICU+JSBjb3VudChhdXRob3IsIHdvcmQpICU+JSBjYXN0X2RmbShhdXRob3IsIHdvcmQsIG4pCgpyY29tbWVudHNfbGRhIDwtIExEQSh0aWR5X21hdHJpeCwgayA9IDUsIGNvbnRyb2wgPSBsaXN0KHNlZWQgPSAxMjM0KSkKCnJjb21tZW50c190b3BpY3MgPC0gdGlkeShyY29tbWVudHNfbGRhLCBtYXRyaXggPSAiYmV0YSIpCgpyY29tbWVudHNfdG9wX3Rlcm1zIDwtIHJjb21tZW50c190b3BpY3MgJT4lCiAgZ3JvdXBfYnkodG9waWMpICU+JQogIHNsaWNlX21heChiZXRhLCBuID0gMTApICU+JQogIHVuZ3JvdXAoKSAlPiUKICBhcnJhbmdlKHRvcGljLC1iZXRhKQoKcmNvbW1lbnRzX3RvcF90ZXJtcyAlPiUKICBtdXRhdGUodGVybSA9IHJlb3JkZXJfd2l0aGluKHRlcm0sIGJldGEsIHRvcGljKSkgJT4lCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IHRlcm0sCiAgICAgICAgICAgICAgbmFtZXNfZnJvbSA9IHRvcGljLAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gYmV0YSkgJT4lCiAgcmVuYW1lKAogICAgIkxlZ2FsIE5ld3MiID0gMiwKICAgICJHYXV0ZW5nICYgbG9ja2Rvd24iID0gMywKICAgICJOYXRpb25zIEFkZHJlc3MiID0gNCwKICAgICJDb3ZpZCAmIEJ1c2luZXNzIFdvcmxkIE5ld3MiID0gNSwKICAgICJWYWNjaW5lcyIgPSA2CiAgKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGMoMiwgMywgNCwgNSwgNiksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInRvcGljIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gImJldGEiKSAlPiUKICBkcm9wX25hKCkgJT4lCiAgZ2dwbG90KGFlcyhiZXRhLCB0ZXJtLCBmaWxsID0gZmFjdG9yKHRvcGljKSkpICsKICBnZW9tX2NvbChzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgZmFjZXRfd3JhcCggfiB0b3BpYywgc2NhbGVzID0gImZyZWUiKSArCiAgc2NhbGVfeV9yZW9yZGVyZWQoKQpgYGAKV2UgZGV0ZXJtaW5lIHRoZSBjb3JyZWN0IG51bWJlciBvZiB0b3BpY3MgaW4gbWVjaGFuaXNtcyBsaWtlIHRoZSBMREEgKExhdGVudCBEaXJpY2hsZXQgQWxsb2NhdGlvbikgYXMgdGhleSBkZXRlcm1pbmUgdGhlIHF1YWxpdHkgb2YgZmVhdHVyZXMgb2YgdGhlIHdvcmRzLgoKQSB0b3BpYyBtb2RlbCBpcyBhIHR5cGUgb2Ygc3RhdGlzdGljIG1vZGVsIGZvciBkaXNjb3ZlcmluZyB0aGUgYWJzdHJhY3QgInRvcGljcyIgdGhhdCBvY2N1ciBpbiBhIGNvbGxlY3Rpb24gb2YgZG9jdW1lbnRzLgoKVG9waWMgbW9kZWxpbmcgaXMgdXNlZCB0byBjbGFzc2lmeSBhbmQgcmV0cmlldmUgaW5mb3JtYXRpb24uIFRoZXNlIG1vZGVscyBjYXB0dXJlIHdvcmQgY29ycmVsYXRpb25zIGluIGEgY29sbGVjdGlvbiBvZiB0ZXh0dWFsIGRvY3VtZW50cyB3aXRoIHRvcGljcy4gSXQgaXMgdmVyeSBkaWZmaWN1bHQgdG8gcGljayB0aGUgcmlnaHQgbnVtYmVyIG9mIHRvcGljcyBmb3IgYSBzcGVjaWZpYyBkYXRhc2V0LiBJdCBpcyBpbXBvcnRhbnQgdG8gZGV0ZXJtaW5lIHRoZSB2YWx1ZSBvZiAnaycuCgpUaGUgaW1wb3J0YW5jZSBvZiB0aGUgdmFsdWUgb2YgJ2snIGlzIHRvIGVuc3VyZSB5b3UgZG8gbm90IG92ZXIgZXN0aW1hdGUgb3IgdW5kZXJlc3RpbWF0ZSB0aGUgZGF0YS4gSWYgeW91IG92ZXIgZXN0aW1hdGUgaXQsIHlvdSB3aWxsIGJlIGxlZnQgd2l0aCB0b3BpY3MgdGhhdCBjYXJyeSB2ZXJ5IGxpdHRsZSBtZWFuaW5nIGFuZCBpZiB5b3UgdW5kZXIgZXN0aW1hdGUgdGhlIGRhdGEsIHlvdSB3aWxsIGxvc2Ugb3V0IG9uIHRvcGljcyB0aGF0IGNvdWxkIGhhdmUgYmVlbiB1c2VmdWwgdG8geW91ciByZXNlYXJjaC4KCkJ5IGxvb2tpbmcgYXQgdGhlIGxvd2VzdCBtaW5pbXVtIGFuZCB0aGUgaGlnaGVzdCBtYXhpbXVtLCB3ZSBjYW4gZGV0ZXJtaW5lIHRoZSAnaycuIFRoaXMgaXMgaG93IHdlIGhhdmUgaW50ZXJwcmV0ZWQgdGhlIGdyYXBocyBwcm9kdWNlZC4gR3JpZmZpdGhzMjAwNCBpcyBub3QgaW5mb3JtYXRpdmUgaW4gdGhpcyBzaXR1YXRpb24gYW5kIGlzIHRoZXJlZm9yZSBpZ25vcmUKClRoaXMgbWV0aG9kIHVzZWQgaGFzIGJlZW4gcHJvdmVkIHRvIHByb2R1Y2UgdGhlIGJlc3QgcmVzdWx0cyBvZiBMREEgd2l0aG91dCBoYXZpbmcgdG8gbWFudWFsbHkgdHVuZSB0aGUgJ2snIHZhbHVlLgpgYGB7ciBHYXAgayBqdXN0aWZ5fQpsaWJyYXJ5KCJsZGF0dW5pbmciKQpsaWJyYXJ5KCJ0b3BpY21vZGVscyIpCgpkYXRhKCJBc3NvY2lhdGVkUHJlc3MiLCBwYWNrYWdlID0gInRvcGljbW9kZWxzIikKZHRtIDwtIEFzc29jaWF0ZWRQcmVzc1sxOjEwLF0KCnJlc3VsdCA8LSBGaW5kVG9waWNzTnVtYmVyKAogIHRpZHlfbWF0cml4LAogIHRvcGljcyA9IHNlcShmcm9tID0gMiwgdG8gPSAxNSwgYnkgPSAxKSwKICBtZXRyaWNzID0gYygiR3JpZmZpdGhzMjAwNCIsICJDYW9KdWFuMjAwOSIsICJBcnVuMjAxMCIsICJEZXZlYXVkMjAxNCIpLAogIG1ldGhvZCA9ICJHaWJicyIsCiAgY29udHJvbCA9IGxpc3Qoc2VlZCA9IDc3KSwKICBtYy5jb3JlcyA9IDJMLAogIHZlcmJvc2UgPSBUUlVFCikKCkZpbmRUb3BpY3NOdW1iZXJfcGxvdChyZXN1bHQpCmBgYAoKCgoKCgoKCg==